From 1ade3a7cdd65314d69dd9eb623bcf7d6c4318ee5 Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Sun, 18 Oct 2020 21:15:03 +0200 Subject: [PATCH 01/12] Added compiler interface --- compiler/compiler.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 compiler/compiler.go diff --git a/compiler/compiler.go b/compiler/compiler.go new file mode 100644 index 0000000..7fa743a --- /dev/null +++ b/compiler/compiler.go @@ -0,0 +1,32 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package compiler + +import ( + "gitlab.com/tymonx/xlogic-toolchain/resource/archive" + "gitlab.com/tymonx/xlogic-toolchain/resource/executable" + "gitlab.com/tymonx/xlogic-toolchain/resource/library" + "gitlab.com/tymonx/xlogic-toolchain/resource/object" +) + +type Compiler interface { + CreateObject(*object.Object) error + + CreateArchive(*archive.Archive) error + + CreateLibrary(*library.Library) error + + CreateExecutable(*executable.Executable) error +} -- GitLab From bf9755907d443e93431679bf66a6250186413f6e Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Mon, 19 Oct 2020 20:03:16 +0200 Subject: [PATCH 02/12] Added factory class --- factory/factory.go | 101 +++++++++++++++++++++++++++++++++ factory/factory_test.go | 123 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 factory/factory.go create mode 100644 factory/factory_test.go diff --git a/factory/factory.go b/factory/factory.go new file mode 100644 index 0000000..081bf91 --- /dev/null +++ b/factory/factory.go @@ -0,0 +1,101 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package factory + +import ( + "sync" + + "gitlab.com/tymonx/xlogic-toolchain/cerr" +) + +// Constructor defines a custom constructor function for creating objects. +type Constructor func(arguments ...interface{}) (object interface{}, err error) + +// Factory defines a factory instance that can create registered object types. +type Factory struct { + constructors map[string]Constructor +} + +var gInstance *Factory // nolint: gochecknoglobals +var gMutex sync.RWMutex // nolint: gochecknoglobals +var gOnce sync.Once // nolint: gochecknoglobals + +// New creates a new factory instance. +func New() *Factory { + return &Factory{ + constructors: make(map[string]Constructor), + } +} + +// Registry registries a new constructor with a given unique id to factory. +func (f *Factory) Registry(name string, constructor Constructor) error { + if constructor == nil { + return cerr.InvalidArgument + } + + if _, ok := f.constructors[name]; ok { + return cerr.InvalidArgument + } + + f.constructors[name] = constructor + + return nil +} + +// Create creates a new object based on given name type. +func (f *Factory) Create(name string, arguments ...interface{}) (object interface{}, err error) { + var constructor Constructor + + var ok bool + + if constructor, ok = f.constructors[name]; !ok { + return nil, cerr.InvalidArgument + } + + if object, err = constructor(arguments...); err != nil { + return nil, cerr.InvalidArgument + } + + if object == nil { + return nil, cerr.InvalidArgument + } + + return object, nil +} + +// Registry registries a new constructor with a given unique id to factory. +func Registry(name string, constructor Constructor) error { + gMutex.Lock() + defer gMutex.Unlock() + + return get().Registry(name, constructor) +} + +// Create creates a new object based on given name type. +func Create(name string, arguments ...interface{}) (object interface{}, err error) { + gMutex.RLock() + defer gMutex.RUnlock() + + return get().Create(name, arguments...) +} + +// get returns global factory instance. +func get() *Factory { + gOnce.Do(func() { + gInstance = New() + }) + + return gInstance +} diff --git a/factory/factory_test.go b/factory/factory_test.go new file mode 100644 index 0000000..587f933 --- /dev/null +++ b/factory/factory_test.go @@ -0,0 +1,123 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package factory_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/cerr" + "gitlab.com/tymonx/xlogic-toolchain/factory" +) + +func TestFactoryNew(test *testing.T) { + assert.NotNil(test, factory.New()) +} + +func TestFactoryRegistry(test *testing.T) { + constructor := func(...interface{}) (interface{}, error) { + return new(struct{}), nil + } + + assert.NoError(test, factory.New().Registry("type", constructor)) +} + +func TestFactoryRegistryGlobal(test *testing.T) { + constructor := func(...interface{}) (interface{}, error) { + return new(struct{}), nil + } + + assert.NoError(test, factory.Registry("type", constructor)) +} + +func TestFactoryRegistryAlreadyRegistered(test *testing.T) { + f := factory.New() + + constructor := func(...interface{}) (interface{}, error) { + return new(struct{}), nil + } + + assert.NoError(test, f.Registry("type", constructor)) + assert.Error(test, f.Registry("type", constructor)) +} + +func TestFactoryRegistryInvalidConstructor(test *testing.T) { + assert.Error(test, factory.New().Registry("type", nil)) +} + +func TestFactoryCreate(test *testing.T) { + f := factory.New() + + constructor := func(...interface{}) (interface{}, error) { + return new(struct{}), nil + } + + assert.NoError(test, f.Registry("type", constructor)) + + object, err := f.Create("type") + + assert.NoError(test, err) + assert.NotNil(test, object) +} + +func TestFactoryCreateGlobal(test *testing.T) { + constructor := func(...interface{}) (interface{}, error) { + return new(struct{}), nil + } + + assert.NoError(test, factory.Registry("type-2", constructor)) + + object, err := factory.Create("type-2") + + assert.NoError(test, err) + assert.NotNil(test, object) +} + +func TestFactoryCreateNotRegistered(test *testing.T) { + object, err := factory.New().Create("type") + + assert.Error(test, err) + assert.Nil(test, object) +} + +func TestFactoryCreateError(test *testing.T) { + f := factory.New() + + constructor := func(...interface{}) (interface{}, error) { + return nil, cerr.InvalidValue + } + + assert.NoError(test, f.Registry("type", constructor)) + + object, err := f.Create("type") + + assert.Error(test, err) + assert.Nil(test, object) +} + +func TestFactoryCreateNotCreated(test *testing.T) { + f := factory.New() + + constructor := func(...interface{}) (interface{}, error) { + return nil, nil + } + + assert.NoError(test, f.Registry("type", constructor)) + + object, err := f.Create("type") + + assert.Error(test, err) + assert.Nil(test, object) +} -- GitLab From e099f99528680f1ab125b4c0e8253dffc2808c10 Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Mon, 26 Oct 2020 21:06:23 +0100 Subject: [PATCH 03/12] Added tests to source file resource --- go.mod | 5 +- go.sum | 4 ++ resource/source/kind/kind.go | 12 ++-- resource/source/kind/kind_test.go | 5 ++ resource/source/source.go | 43 +++++++++++++ resource/source/source_test.go | 101 ++++++++++++++++++++++++++++++ resource/source/sources.go | 45 ++++++++++++- resource/source/sources_test.go | 73 +++++++++++++++++++-- 8 files changed, 272 insertions(+), 16 deletions(-) create mode 100644 resource/source/source_test.go diff --git a/go.mod b/go.mod index d0b2f66..c74305c 100644 --- a/go.mod +++ b/go.mod @@ -16,4 +16,7 @@ module gitlab.com/tymonx/xlogic-toolchain go 1.14 -require github.com/stretchr/testify v1.6.1 +require ( + github.com/stretchr/testify v1.6.1 + gitlab.com/tymonx/go-error v1.1.0 +) diff --git a/go.sum b/go.sum index 56d62e7..5298066 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,10 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gitlab.com/tymonx/go-error v1.1.0 h1:ynB2GC1Hw3pVhDAoAeAiMmSDBtoM0OXYffWrRIGmDOE= +gitlab.com/tymonx/go-error v1.1.0/go.mod h1:hN0YcBOqVJCinZxDlKg2xn94U4F+h/yQZtsgPa6jpmY= +gitlab.com/tymonx/go-formatter v1.0.0 h1:OMq9YE+kQfPQExX4tW/3/9A5SjJqvxqVRNezOh35qDI= +gitlab.com/tymonx/go-formatter v1.0.0/go.mod h1:mgO1gntIZoYP8XyxVGYwfMe7PTctf0DBc/BIFaFwlOM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/resource/source/kind/kind.go b/resource/source/kind/kind.go index 270cc95..cc4f27e 100644 --- a/resource/source/kind/kind.go +++ b/resource/source/kind/kind.go @@ -96,14 +96,14 @@ func (k *Kind) String() string { return gToString[*k] } -// UnmarshalJSON decodes from JSON to kind. -func (k *Kind) UnmarshalJSON(data []byte) error { - *k = FromString(strings.Trim(string(data), `"`)) +// UnmarshalText decodes from text to kind. +func (k *Kind) UnmarshalText(data []byte) error { + *k = FromString(string(data)) return nil } -// MarshalJSON decodes from kind to JSON. -func (k *Kind) MarshalJSON() (data []byte, err error) { - return []byte(`"` + k.String() + `"`), nil +// MarshalText decodes from kind to text. +func (k *Kind) MarshalText() (data []byte, err error) { + return []byte(k.String()), nil } diff --git a/resource/source/kind/kind_test.go b/resource/source/kind/kind_test.go index bb34f90..cc88e16 100644 --- a/resource/source/kind/kind_test.go +++ b/resource/source/kind/kind_test.go @@ -46,6 +46,11 @@ func TestKindFromPath(test *testing.T) { assert.Equal(test, kind.SystemVerilog, kind.FromPath("dir/file.sV")) } +func TestKindIs(test *testing.T) { + assert.True(test, kind.Is("dir/file.vhd")) + assert.False(test, kind.Is("dir/dir2")) +} + func TestKindString(test *testing.T) { k := kind.FromPath("dir/file.sv") diff --git a/resource/source/source.go b/resource/source/source.go index e3a80b1..6b2c5d0 100644 --- a/resource/source/source.go +++ b/resource/source/source.go @@ -15,6 +15,9 @@ package source import ( + "encoding/json" + + "gitlab.com/tymonx/go-error/rterror" "gitlab.com/tymonx/xlogic-toolchain/path" "gitlab.com/tymonx/xlogic-toolchain/resource/source/kind" ) @@ -42,3 +45,43 @@ func Is(file path.Path) bool { func (s *Source) String() string { return s.Path.String() } + +// UnmarshalText decodes text to source file path. +func (s *Source) UnmarshalText(data []byte) error { + s.Path = path.Path(data) + s.Kind = kind.FromPath(s.Path) + + return nil +} + +// UnmarshalJSON decodes JSON to source file path. +func (s *Source) UnmarshalJSON(data []byte) error { + switch data[0] { + case '{': + case '"': + return s.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *s = Source{} + return nil + default: + return rterror.New("invalid JSON type") + } + + object := new(struct { + Kind kind.Kind `json:"kind"` + Path path.Path `json:"path"` + }) + + if err := json.Unmarshal(data, object); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + s.Kind = object.Kind + s.Path = object.Path + + if s.Kind == kind.Unknown { + s.Kind = kind.FromPath(s.Path) + } + + return nil +} diff --git a/resource/source/source_test.go b/resource/source/source_test.go new file mode 100644 index 0000000..a599b95 --- /dev/null +++ b/resource/source/source_test.go @@ -0,0 +1,101 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package source_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/path" + "gitlab.com/tymonx/xlogic-toolchain/resource/source" + "gitlab.com/tymonx/xlogic-toolchain/resource/source/kind" +) + +func TestSourceNew(test *testing.T) { + want := "file.c" + + s := source.New(path.Path(want)) + + assert.NotNil(test, s) + assert.Equal(test, kind.C, s.Kind) + assert.Equal(test, "c", s.Kind.String()) + assert.Equal(test, want, s.Path.String()) +} + +func TestSourceString(test *testing.T) { + want := "file.sv" + + assert.NotNil(test, want, source.New(path.Path(want)).String()) +} + +func TestSourceIs(test *testing.T) { + assert.True(test, source.Is("dir/file.c++")) + assert.False(test, source.Is("/dir/dir")) +} + +func TestSourceUnmarshalText(test *testing.T) { + want := "dir/file.sv" + + s := new(source.Source) + + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), s)) + + assert.Equal(test, want, s.Path.String()) + assert.Equal(test, kind.SystemVerilog, s.Kind) + assert.Equal(test, "systemverilog", s.Kind.String()) +} + +func TestSourceUnmarshalJSONObject(test *testing.T) { + want := "dir/file.tcl" + + s := new(source.Source) + + assert.NoError(test, json.Unmarshal([]byte(` { "path": "`+want+`" } `), s)) + + assert.Equal(test, want, s.Path.String()) + assert.Equal(test, kind.TCL, s.Kind) + assert.Equal(test, "tcl", s.Kind.String()) +} + +func TestSourceUnmarshalJSONNull(test *testing.T) { + s := new(source.Source) + + assert.NoError(test, json.Unmarshal([]byte(` null `), s)) + + assert.Empty(test, s.Path.String()) + assert.Empty(test, s.Kind.String()) + assert.Equal(test, kind.Unknown, s.Kind) +} + +func TestSourceUnmarshalJSONError(test *testing.T) { + s := new(source.Source) + + assert.Error(test, json.Unmarshal([]byte(`{"path":5}`), s)) + + assert.Empty(test, s.Path.String()) + assert.Empty(test, s.Kind.String()) + assert.Equal(test, kind.Unknown, s.Kind) +} + +func TestSourceUnmarshalJSONInvalid(test *testing.T) { + s := new(source.Source) + + assert.Error(test, json.Unmarshal([]byte(`true`), s)) + + assert.Empty(test, s.Path.String()) + assert.Empty(test, s.Kind.String()) + assert.Equal(test, kind.Unknown, s.Kind) +} diff --git a/resource/source/sources.go b/resource/source/sources.go index 857e075..8a63561 100644 --- a/resource/source/sources.go +++ b/resource/source/sources.go @@ -15,13 +15,52 @@ package source import ( + "encoding/json" + + "gitlab.com/tymonx/go-error/rterror" "gitlab.com/tymonx/xlogic-toolchain/path" ) // Sources defines a list of source files. type Sources []*Source -// Add adds source file. -func (s *Sources) Add(file path.Path) { - *s = append(*s, New(file)) +// UnmarshalText decodes text to source file path. +func (s *Sources) UnmarshalText(data []byte) error { + *s = Sources{New(path.Path(data))} + + return nil +} + +// UnmarshalJSON decodes JSON to source file path. +func (s *Sources) UnmarshalJSON(data []byte) error { + switch data[0] { + case '[': + case '{': + object := new(Source) + + if err := json.Unmarshal(data, object); err != nil { + return err + } + + *s = Sources{object} + + return nil + case '"': + return s.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *s = Sources{} + return nil + default: + return rterror.New("invalid JSON type") + } + + sources := []*Source{} + + if err := json.Unmarshal(data, &sources); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + *s = sources + + return nil } diff --git a/resource/source/sources_test.go b/resource/source/sources_test.go index ec39833..7e4ae4a 100644 --- a/resource/source/sources_test.go +++ b/resource/source/sources_test.go @@ -15,19 +15,80 @@ package source_test import ( + "encoding/json" "testing" "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/path" "gitlab.com/tymonx/xlogic-toolchain/resource/source" + "gitlab.com/tymonx/xlogic-toolchain/resource/source/kind" ) -func TestSourceNew(test *testing.T) { - assert.NotNil(test, source.New("file.c")) +func TestSourcesUnmarshalText(test *testing.T) { + want := "dir/file.c++" + + var s source.Sources + + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), &s)) + + assert.Len(test, s, 1) + assert.Equal(test, kind.Cxx, s[0].Kind) + assert.Equal(test, "c++", s[0].Kind.String()) + assert.Equal(test, want, s[0].Path.String()) +} + +func TestSourcesUnmarshalJSON(test *testing.T) { + var s source.Sources + + assert.NoError(test, json.Unmarshal([]byte(` ["dir/file.c", { "path": "file.tcl" }]`), &s)) + + assert.Len(test, s, 2) + + assert.Equal(test, kind.C, s[0].Kind) + assert.Equal(test, "c", s[0].Kind.String()) + assert.Equal(test, "dir/file.c", s[0].Path.String()) + + assert.Equal(test, kind.TCL, s[1].Kind) + assert.Equal(test, "tcl", s[1].Kind.String()) + assert.Equal(test, "file.tcl", s[1].Path.String()) +} + +func TestSourcesUnmarshalJSONObject(test *testing.T) { + want := "dir/file.json" + + var s source.Sources + + assert.NoError(test, json.Unmarshal([]byte(` { "path": "`+want+`" } `), &s)) + + assert.Len(test, s, 1) + assert.Equal(test, want, s[0].Path.String()) + assert.Equal(test, kind.JSON, s[0].Kind) + assert.Equal(test, "json", s[0].Kind.String()) +} + +func TestSourcesUnmarshalJSONNull(test *testing.T) { + var s source.Sources + + assert.NoError(test, json.Unmarshal([]byte(` null `), &s)) + assert.Empty(test, s) +} + +func TestSourcesUnmarshalJSONError(test *testing.T) { + var s source.Sources + + assert.Error(test, json.Unmarshal([]byte(`[5]`), &s)) + assert.Empty(test, s) +} + +func TestSourcesUnmarshalJSONObjectError(test *testing.T) { + var s source.Sources + + assert.Error(test, json.Unmarshal([]byte(`{"path":5}`), &s)) + assert.Empty(test, s) } -func TestSourceString(test *testing.T) { - want := "file.sv" +func TestSourcesUnmarshalJSONInvalid(test *testing.T) { + var s source.Sources - assert.NotNil(test, want, source.New(path.Path(want)).String()) + assert.Error(test, json.Unmarshal([]byte(`true`), &s)) + assert.Empty(test, s) } -- GitLab From 188df008f21608715bd80cd83058efd865772ec4 Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Mon, 26 Oct 2020 22:33:24 +0100 Subject: [PATCH 04/12] Added tests to include resource --- resource/include/include.go | 43 +++++++++++++++- resource/include/include_test.go | 83 +++++++++++++++++++++++++++++++ resource/include/includes.go | 46 ++++++++++++++--- resource/include/includes_test.go | 62 ++++++++++++++++++++--- 4 files changed, 219 insertions(+), 15 deletions(-) create mode 100644 resource/include/include_test.go diff --git a/resource/include/include.go b/resource/include/include.go index 085e79c..14ba87e 100644 --- a/resource/include/include.go +++ b/resource/include/include.go @@ -15,10 +15,13 @@ package include import ( + "encoding/json" + + "gitlab.com/tymonx/go-error/rterror" "gitlab.com/tymonx/xlogic-toolchain/path" ) -// Include defines a single include path. +// Include defines a single include directory path. type Include struct { Path path.Path `json:"path,omitempty"` } @@ -34,3 +37,41 @@ func New(dir path.Path) *Include { Path: dir, } } + +// String returns path string. +func (i *Include) String() string { + return i.Path.String() +} + +// UnmarshalText decodes text to include directory path. +func (i *Include) UnmarshalText(data []byte) error { + i.Path = path.Path(data) + + return nil +} + +// UnmarshalJSON decodes JSON to include directory path. +func (i *Include) UnmarshalJSON(data []byte) error { + switch data[0] { + case '{': + case '"': + return i.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *i = Include{} + return nil + default: + return rterror.New("invalid JSON type") + } + + object := new(struct { + Path path.Path `json:"path"` + }) + + if err := json.Unmarshal(data, object); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + i.Path = object.Path + + return nil +} diff --git a/resource/include/include_test.go b/resource/include/include_test.go new file mode 100644 index 0000000..e91a64d --- /dev/null +++ b/resource/include/include_test.go @@ -0,0 +1,83 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package include_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/path" + "gitlab.com/tymonx/xlogic-toolchain/resource/include" +) + +func TestIncludeNew(test *testing.T) { + want := "dir/dir/dir" + + i := include.New(path.Path(want)) + + assert.NotNil(test, i) + assert.Equal(test, want, i.Path.String()) +} + +func TestIncludeString(test *testing.T) { + want := "dirA" + + assert.NotNil(test, want, include.New(path.Path(want)).String()) +} + +func TestIncludeIs(test *testing.T) { + assert.True(test, include.Is("dir/")) + assert.False(test, include.Is("file.c")) +} + +func TestIncludeUnmarshalText(test *testing.T) { + want := "dirB" + + i := new(include.Include) + + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), i)) + assert.Equal(test, want, i.Path.String()) +} + +func TestIncludeUnmarshalJSONObject(test *testing.T) { + want := "dirC" + + i := new(include.Include) + + assert.NoError(test, json.Unmarshal([]byte(` { "path": "`+want+`" } `), i)) + assert.Equal(test, want, i.Path.String()) +} + +func TestIncludeUnmarshalJSONNull(test *testing.T) { + i := new(include.Include) + + assert.NoError(test, json.Unmarshal([]byte(` null `), i)) + assert.Empty(test, i.Path.String()) +} + +func TestIncludeUnmarshalJSONError(test *testing.T) { + i := new(include.Include) + + assert.Error(test, json.Unmarshal([]byte(`{"path":5}`), i)) + assert.Empty(test, i.Path.String()) +} + +func TestIncludeUnmarshalJSONInvalid(test *testing.T) { + i := new(include.Include) + + assert.Error(test, json.Unmarshal([]byte(`true`), i)) + assert.Empty(test, i.Path.String()) +} diff --git a/resource/include/includes.go b/resource/include/includes.go index a9cf512..e904b15 100644 --- a/resource/include/includes.go +++ b/resource/include/includes.go @@ -15,20 +15,52 @@ package include import ( + "encoding/json" + + "gitlab.com/tymonx/go-error/rterror" "gitlab.com/tymonx/xlogic-toolchain/path" ) -// Includes defines a list of include paths. +// Includes defines a list of include directory paths. type Includes []*Include -// Strings returns string representation. -func (*Includes) String() string { - return "" +// UnmarshalText decodes text to include directory path. +func (i *Includes) UnmarshalText(data []byte) error { + *i = Includes{New(path.Path(data))} + + return nil } -// Set is called once, in command line order, for each flag present. -func (i *Includes) Set(value string) error { - *i = append(*i, New(path.Path(value))) +// UnmarshalJSON decodes JSON to include directory path. +func (i *Includes) UnmarshalJSON(data []byte) error { + switch data[0] { + case '[': + case '{': + object := new(Include) + + if err := json.Unmarshal(data, object); err != nil { + return err + } + + *i = Includes{object} + + return nil + case '"': + return i.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *i = Includes{} + return nil + default: + return rterror.New("invalid JSON type") + } + + includes := []*Include{} + + if err := json.Unmarshal(data, &includes); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + *i = includes return nil } diff --git a/resource/include/includes_test.go b/resource/include/includes_test.go index 7d2e8da..5cc9c28 100644 --- a/resource/include/includes_test.go +++ b/resource/include/includes_test.go @@ -15,21 +15,69 @@ package include_test import ( - "flag" + "encoding/json" "testing" "github.com/stretchr/testify/assert" "gitlab.com/tymonx/xlogic-toolchain/resource/include" ) -func TestSourcesSet(test *testing.T) { +func TestIncludesUnmarshalText(test *testing.T) { + want := "dirA/dirB" + var i include.Includes - fs := flag.NewFlagSet("example", flag.ExitOnError) - fs.Var(&i, "I", "") + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), &i)) + + assert.Len(test, i, 1) + assert.Equal(test, want, i[0].Path.String()) +} + +func TestIncludesUnmarshalJSON(test *testing.T) { + var i include.Includes + + assert.NoError(test, json.Unmarshal([]byte(` ["dirB", { "path": "dirC/dirD" }]`), &i)) - assert.NoError(test, fs.Parse([]string{"-I", "/dir/dir", "-I", "/dir", "file"})) assert.Len(test, i, 2) - assert.Equal(test, "/dir/dir", i[0].Path.String()) - assert.Equal(test, "/dir", i[1].Path.String()) + assert.Equal(test, "dirB", i[0].Path.String()) + assert.Equal(test, "dirC/dirD", i[1].Path.String()) +} + +func TestIncludesUnmarshalJSONObject(test *testing.T) { + want := "dirE/dirF" + + var i include.Includes + + assert.NoError(test, json.Unmarshal([]byte(` { "path": "`+want+`" } `), &i)) + + assert.Len(test, i, 1) + assert.Equal(test, want, i[0].Path.String()) +} + +func TestIncludesUnmarshalJSONNull(test *testing.T) { + var i include.Includes + + assert.NoError(test, json.Unmarshal([]byte(` null `), &i)) + assert.Empty(test, i) +} + +func TestIncludesUnmarshalJSONError(test *testing.T) { + var i include.Includes + + assert.Error(test, json.Unmarshal([]byte(`[5]`), &i)) + assert.Empty(test, i) +} + +func TestIncludesUnmarshalJSONObjectError(test *testing.T) { + var i include.Includes + + assert.Error(test, json.Unmarshal([]byte(`{"path":5}`), &i)) + assert.Empty(test, i) +} + +func TestIncludesUnmarshalJSONInvalid(test *testing.T) { + var i include.Includes + + assert.Error(test, json.Unmarshal([]byte(`true`), &i)) + assert.Empty(test, i) } -- GitLab From 1c32fdf34de9e4833b0ae73e6159d7c3b5213b32 Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Mon, 26 Oct 2020 23:21:42 +0100 Subject: [PATCH 05/12] Added tests to header resource --- resource/header/header.go | 48 ++++++++++++++ resource/header/header_test.go | 101 ++++++++++++++++++++++++++++++ resource/header/headers.go | 44 +++++++++++-- resource/header/headers_test.go | 73 ++++++++++++++++++--- resource/header/kind/kind.go | 13 ++-- resource/header/kind/kind_test.go | 5 ++ resource/source/kind/kind.go | 1 - 7 files changed, 264 insertions(+), 21 deletions(-) create mode 100644 resource/header/header_test.go diff --git a/resource/header/header.go b/resource/header/header.go index ad803f3..8e54258 100644 --- a/resource/header/header.go +++ b/resource/header/header.go @@ -15,6 +15,9 @@ package header import ( + "encoding/json" + + "gitlab.com/tymonx/go-error/rterror" "gitlab.com/tymonx/xlogic-toolchain/path" "gitlab.com/tymonx/xlogic-toolchain/resource/header/kind" ) @@ -37,3 +40,48 @@ func New(file path.Path) *Header { Path: file, } } + +// String returns path string. +func (h *Header) String() string { + return h.Path.String() +} + +// UnmarshalText decodes text to header file path. +func (h *Header) UnmarshalText(data []byte) error { + h.Path = path.Path(data) + h.Kind = kind.FromPath(h.Path) + + return nil +} + +// UnmarshalJSON decodes JSON to header file path. +func (h *Header) UnmarshalJSON(data []byte) error { + switch data[0] { + case '{': + case '"': + return h.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *h = Header{} + return nil + default: + return rterror.New("invalid JSON type") + } + + object := new(struct { + Kind kind.Kind `json:"kind"` + Path path.Path `json:"path"` + }) + + if err := json.Unmarshal(data, object); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + h.Kind = object.Kind + h.Path = object.Path + + if h.Kind == kind.Unknown { + h.Kind = kind.FromPath(h.Path) + } + + return nil +} diff --git a/resource/header/header_test.go b/resource/header/header_test.go new file mode 100644 index 0000000..3e34751 --- /dev/null +++ b/resource/header/header_test.go @@ -0,0 +1,101 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package header_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/path" + "gitlab.com/tymonx/xlogic-toolchain/resource/header" + "gitlab.com/tymonx/xlogic-toolchain/resource/header/kind" +) + +func TestHeaderNew(test *testing.T) { + want := "file.h" + + h := header.New(path.Path(want)) + + assert.NotNil(test, h) + assert.Equal(test, kind.C, h.Kind) + assert.Equal(test, "c", h.Kind.String()) + assert.Equal(test, want, h.Path.String()) +} + +func TestHeaderString(test *testing.T) { + want := "file.svh" + + assert.NotNil(test, want, header.New(path.Path(want)).String()) +} + +func TestHeaderIs(test *testing.T) { + assert.True(test, header.Is("dir/file.hpp")) + assert.False(test, header.Is("/dir/dir")) +} + +func TestHeaderUnmarshalText(test *testing.T) { + want := "dir/file.svh" + + h := new(header.Header) + + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), h)) + + assert.Equal(test, want, h.Path.String()) + assert.Equal(test, kind.SystemVerilog, h.Kind) + assert.Equal(test, "systemverilog", h.Kind.String()) +} + +func TestHeaderUnmarshalJSONObject(test *testing.T) { + want := "dir/file.h++" + + h := new(header.Header) + + assert.NoError(test, json.Unmarshal([]byte(` { "path": "`+want+`" } `), h)) + + assert.Equal(test, want, h.Path.String()) + assert.Equal(test, kind.Cxx, h.Kind) + assert.Equal(test, "c++", h.Kind.String()) +} + +func TestHeaderUnmarshalJSONNull(test *testing.T) { + h := new(header.Header) + + assert.NoError(test, json.Unmarshal([]byte(` null `), h)) + + assert.Empty(test, h.Path.String()) + assert.Empty(test, h.Kind.String()) + assert.Equal(test, kind.Unknown, h.Kind) +} + +func TestHeaderUnmarshalJSONError(test *testing.T) { + h := new(header.Header) + + assert.Error(test, json.Unmarshal([]byte(`{"path":5}`), h)) + + assert.Empty(test, h.Path.String()) + assert.Empty(test, h.Kind.String()) + assert.Equal(test, kind.Unknown, h.Kind) +} + +func TestHeaderUnmarshalJSONInvalid(test *testing.T) { + h := new(header.Header) + + assert.Error(test, json.Unmarshal([]byte(`true`), h)) + + assert.Empty(test, h.Path.String()) + assert.Empty(test, h.Kind.String()) + assert.Equal(test, kind.Unknown, h.Kind) +} diff --git a/resource/header/headers.go b/resource/header/headers.go index 00cce43..a3ccbbc 100644 --- a/resource/header/headers.go +++ b/resource/header/headers.go @@ -15,20 +15,52 @@ package header import ( + "encoding/json" + + "gitlab.com/tymonx/go-error/rterror" "gitlab.com/tymonx/xlogic-toolchain/path" ) // Headers defines a list of header files. type Headers []*Header -// Strings returns string representation. -func (*Headers) String() string { - return "" +// UnmarshalText decodes text to header file path. +func (h *Headers) UnmarshalText(data []byte) error { + *h = Headers{New(path.Path(data))} + + return nil } -// Set is called once, in command line order, for each flag present. -func (h *Headers) Set(value string) error { - *h = append(*h, New(path.Path(value))) +// UnmarshalJSON decodes JSON to header file path. +func (h *Headers) UnmarshalJSON(data []byte) error { + switch data[0] { + case '[': + case '{': + object := new(Header) + + if err := json.Unmarshal(data, object); err != nil { + return err + } + + *h = Headers{object} + + return nil + case '"': + return h.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *h = Headers{} + return nil + default: + return rterror.New("invalid JSON type") + } + + sources := []*Header{} + + if err := json.Unmarshal(data, &sources); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + *h = sources return nil } diff --git a/resource/header/headers_test.go b/resource/header/headers_test.go index dd8757b..e1262a6 100644 --- a/resource/header/headers_test.go +++ b/resource/header/headers_test.go @@ -15,21 +15,80 @@ package header_test import ( - "flag" + "encoding/json" "testing" "github.com/stretchr/testify/assert" "gitlab.com/tymonx/xlogic-toolchain/resource/header" + "gitlab.com/tymonx/xlogic-toolchain/resource/header/kind" ) -func TestSourcesSet(test *testing.T) { +func TestHeadersUnmarshalText(test *testing.T) { + want := "dir/file.hpp" + + var h header.Headers + + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), &h)) + + assert.Len(test, h, 1) + assert.Equal(test, kind.Cxx, h[0].Kind) + assert.Equal(test, "c++", h[0].Kind.String()) + assert.Equal(test, want, h[0].Path.String()) +} + +func TestHeadersUnmarshalJSON(test *testing.T) { var h header.Headers - fs := flag.NewFlagSet("example", flag.ExitOnError) - fs.Var(&h, "include", "") + assert.NoError(test, json.Unmarshal([]byte(` ["dir/file.h", { "path": "file.svh" }]`), &h)) - assert.NoError(test, fs.Parse([]string{"-include", "/dir/file.h", "-include", "file.h", "file"})) assert.Len(test, h, 2) - assert.Equal(test, "/dir/file.h", h[0].Path.String()) - assert.Equal(test, "file.h", h[1].Path.String()) + + assert.Equal(test, kind.C, h[0].Kind) + assert.Equal(test, "c", h[0].Kind.String()) + assert.Equal(test, "dir/file.h", h[0].Path.String()) + + assert.Equal(test, kind.SystemVerilog, h[1].Kind) + assert.Equal(test, "systemverilog", h[1].Kind.String()) + assert.Equal(test, "file.svh", h[1].Path.String()) +} + +func TestHeadersUnmarshalJSONObject(test *testing.T) { + want := "dir/file.vh" + + var h header.Headers + + assert.NoError(test, json.Unmarshal([]byte(` { "path": "`+want+`" } `), &h)) + + assert.Len(test, h, 1) + assert.Equal(test, want, h[0].Path.String()) + assert.Equal(test, kind.Verilog, h[0].Kind) + assert.Equal(test, "verilog", h[0].Kind.String()) +} + +func TestHeadersUnmarshalJSONNull(test *testing.T) { + var h header.Headers + + assert.NoError(test, json.Unmarshal([]byte(` null `), &h)) + assert.Empty(test, h) +} + +func TestHeadersUnmarshalJSONError(test *testing.T) { + var h header.Headers + + assert.Error(test, json.Unmarshal([]byte(`[5]`), &h)) + assert.Empty(test, h) +} + +func TestHeadersUnmarshalJSONObjectError(test *testing.T) { + var h header.Headers + + assert.Error(test, json.Unmarshal([]byte(`{"path":5}`), &h)) + assert.Empty(test, h) +} + +func TestHeadersUnmarshalJSONInvalid(test *testing.T) { + var h header.Headers + + assert.Error(test, json.Unmarshal([]byte(`true`), &h)) + assert.Empty(test, h) } diff --git a/resource/header/kind/kind.go b/resource/header/kind/kind.go index b0109b7..27fcb90 100644 --- a/resource/header/kind/kind.go +++ b/resource/header/kind/kind.go @@ -78,14 +78,13 @@ func (k *Kind) String() string { return gToString[*k] } -// UnmarshalJSON decodes from JSON to kind. -func (k *Kind) UnmarshalJSON(data []byte) error { - *k = FromString(strings.Trim(string(data), `"`)) - +// UnmarshalText decodes from text to kind. +func (k *Kind) UnmarshalText(data []byte) error { + *k = FromString(string(data)) return nil } -// MarshalJSON decodes from kind to JSON. -func (k *Kind) MarshalJSON() (data []byte, err error) { - return []byte(`"` + k.String() + `"`), nil +// MarshalText decodes from kind to text. +func (k *Kind) MarshalText() (data []byte, err error) { + return []byte(k.String()), nil } diff --git a/resource/header/kind/kind_test.go b/resource/header/kind/kind_test.go index f954e6b..06c1d58 100644 --- a/resource/header/kind/kind_test.go +++ b/resource/header/kind/kind_test.go @@ -40,6 +40,11 @@ func TestKindFromPath(test *testing.T) { assert.Equal(test, kind.SystemVerilog, kind.FromPath("dir/file.sVh")) } +func TestKindIs(test *testing.T) { + assert.True(test, kind.Is("dir/file.svh")) + assert.False(test, kind.Is("dir/file.sv")) +} + func TestKindString(test *testing.T) { k := kind.FromPath("dir/file.svh") diff --git a/resource/source/kind/kind.go b/resource/source/kind/kind.go index cc4f27e..d7ba90e 100644 --- a/resource/source/kind/kind.go +++ b/resource/source/kind/kind.go @@ -99,7 +99,6 @@ func (k *Kind) String() string { // UnmarshalText decodes from text to kind. func (k *Kind) UnmarshalText(data []byte) error { *k = FromString(string(data)) - return nil } -- GitLab From f690f89dd793aef615ea51178a47eb0225e53add Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Tue, 27 Oct 2020 00:12:28 +0100 Subject: [PATCH 06/12] Added tests to define resource --- resource/define/define.go | 61 ++++++++++---------------- resource/define/define_test.go | 72 +++++++++++++++--------------- resource/define/defines.go | 47 +++++++++++++++++--- resource/define/defines_test.go | 78 +++++++++++++++++++++++++-------- resource/define/undefines.go | 32 -------------- resource/header/headers.go | 6 +-- 6 files changed, 162 insertions(+), 134 deletions(-) delete mode 100644 resource/define/undefines.go diff --git a/resource/define/define.go b/resource/define/define.go index 4c6ca57..3dcc2a6 100644 --- a/resource/define/define.go +++ b/resource/define/define.go @@ -18,14 +18,13 @@ import ( "encoding/json" "strings" - "gitlab.com/tymonx/xlogic-toolchain/cerr" + "gitlab.com/tymonx/go-error/rterror" ) // Define defines define. type Define struct { Name string `json:"name,omitempty"` Value string `json:"value,omitempty"` - Unset bool `json:"unset,omitempty"` } // New creates a new define object. @@ -43,12 +42,6 @@ func New(value string) *Define { return d } -// Undef sets unset flag. -func (d *Define) Undef() *Define { - d.Unset = true - return d -} - // String returns define as string. func (d *Define) String() string { if d.Value == "" { @@ -58,42 +51,36 @@ func (d *Define) String() string { return d.Name + "=" + d.Value } +// UnmarshalText decodes text to define. +func (d *Define) UnmarshalText(data []byte) error { + *d = *New(string(data)) + return nil +} + // UnmarshalJSON decodes JSON to define. func (d *Define) UnmarshalJSON(data []byte) error { switch data[0] { - case '"': - *d = *New(strings.Trim(string(data), `"`)) case '{': - object := make(map[string]interface{}) - - if err := json.Unmarshal(data, &object); err != nil { - return err - } - - var def Define - - if val, ok := object["name"]; ok { - if def.Name, ok = val.(string); !ok { - return cerr.InvalidValue - } - } - - if val, ok := object["value"]; ok { - if def.Value, ok = val.(string); !ok { - return cerr.InvalidValue - } - } + case '"': + return d.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *d = Define{} + return nil + default: + return rterror.New("invalid JSON type") + } - if val, ok := object["unset"]; ok { - if def.Unset, ok = val.(bool); !ok { - return cerr.InvalidValue - } - } + object := new(struct { + Name string `json:"name"` + Value string `json:"value"` + }) - *d = def - default: - return cerr.InvalidValue + if err := json.Unmarshal(data, object); err != nil { + return rterror.New("error occurred while decoding JSON", err) } + d.Name = strings.TrimSpace(object.Name) + d.Value = strings.TrimSpace(object.Value) + return nil } diff --git a/resource/define/define_test.go b/resource/define/define_test.go index 0ba4fa3..bb350ee 100644 --- a/resource/define/define_test.go +++ b/resource/define/define_test.go @@ -23,73 +23,71 @@ import ( ) func TestDefineNew(test *testing.T) { - want := "FOO" + want := "Name=value" d := define.New(want) - assert.Equal(test, want, d.Name) - assert.Empty(test, d.Value) + assert.NotNil(test, d) + assert.Equal(test, "Name", d.Name) + assert.Equal(test, "value", d.Value) + assert.Equal(test, want, d.String()) } -func TestDefineSetValue(test *testing.T) { - d := define.New("FAB=BAR") +func TestDefineString(test *testing.T) { + want := "NAME=5" - assert.Equal(test, "FAB", d.Name) - assert.Equal(test, "BAR", d.Value) + assert.NotNil(test, want, define.New(want).String()) } -func TestDefineString(test *testing.T) { - var d define.Define +func TestDefineUnmarshalText(test *testing.T) { + want := " MYDEF = text " - want := "XYZ" + d := new(define.Define) - d.Name = want + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), d)) - assert.Equal(test, want, d.String()) + assert.Equal(test, "MYDEF=text", d.String()) + assert.Equal(test, "MYDEF", d.Name) + assert.Equal(test, "text", d.Value) } -func TestDefineStringValue(test *testing.T) { - var d define.Define - - d.Name = "GOO" - d.Value = "Test" - - assert.Equal(test, "GOO=Test", d.String()) -} +func TestDefineUnmarshalJSONObject(test *testing.T) { + want := "DEFINE" -func TestDefineUnmarshalJSONString(test *testing.T) { - var d define.Define + d := new(define.Define) - want := "ABC=Test" + assert.NoError(test, json.Unmarshal([]byte(` { "name": "`+want+`" } `), d)) - assert.NoError(test, json.Unmarshal([]byte(` " `+want+` " `), &d)) assert.Equal(test, want, d.String()) - assert.Equal(test, "ABC", d.Name) - assert.Equal(test, "Test", d.Value) + assert.Equal(test, want, d.Name) + assert.Empty(test, d.Value) } -func TestDefineUnmarshalJSONObject(test *testing.T) { - var d define.Define +func TestDefineUnmarshalJSONNull(test *testing.T) { + d := new(define.Define) - assert.NoError(test, json.Unmarshal([]byte(` {"name": "Y", "value": "A"} `), &d)) - assert.Equal(test, "Y=A", d.String()) - assert.Equal(test, "Y", d.Name) - assert.Equal(test, "A", d.Value) + assert.NoError(test, json.Unmarshal([]byte(` null `), d)) + + assert.Empty(test, d.String()) + assert.Empty(test, d.Name) + assert.Empty(test, d.Value) } -func TestDefineUnmarshalJSONObjectInvalid(test *testing.T) { - var d define.Define +func TestDefineUnmarshalJSONError(test *testing.T) { + d := new(define.Define) + + assert.Error(test, json.Unmarshal([]byte(`{"name":5}`), d)) - assert.Error(test, json.Unmarshal([]byte(` {"name": "Y", "value": []} `), &d)) assert.Empty(test, d.String()) assert.Empty(test, d.Name) assert.Empty(test, d.Value) } func TestDefineUnmarshalJSONInvalid(test *testing.T) { - var d define.Define + d := new(define.Define) + + assert.Error(test, json.Unmarshal([]byte(`true`), d)) - assert.Error(test, json.Unmarshal([]byte(` 3 `), &d)) assert.Empty(test, d.String()) assert.Empty(test, d.Name) assert.Empty(test, d.Value) diff --git a/resource/define/defines.go b/resource/define/defines.go index 9ab025a..238a067 100644 --- a/resource/define/defines.go +++ b/resource/define/defines.go @@ -14,17 +14,52 @@ package define +import ( + "encoding/json" + + "gitlab.com/tymonx/go-error/rterror" +) + // Defines defines a list of defines. type Defines []*Define -// Strings returns string representation. -func (*Defines) String() string { - return "" +// UnmarshalText decodes text to define. +func (d *Defines) UnmarshalText(data []byte) error { + *d = Defines{New(string(data))} + + return nil } -// Set is called once, in command line order, for each flag present. -func (d *Defines) Set(value string) error { - *d = append(*d, New(value)) +// UnmarshalJSON decodes JSON to define. +func (d *Defines) UnmarshalJSON(data []byte) error { + switch data[0] { + case '[': + case '{': + object := new(Define) + + if err := json.Unmarshal(data, object); err != nil { + return err + } + + *d = Defines{object} + + return nil + case '"': + return d.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *d = Defines{} + return nil + default: + return rterror.New("invalid JSON type") + } + + defines := []*Define{} + + if err := json.Unmarshal(data, &defines); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + *d = defines return nil } diff --git a/resource/define/defines_test.go b/resource/define/defines_test.go index b0207ce..007f41f 100644 --- a/resource/define/defines_test.go +++ b/resource/define/defines_test.go @@ -15,39 +15,79 @@ package define_test import ( - "flag" + "encoding/json" "testing" "github.com/stretchr/testify/assert" "gitlab.com/tymonx/xlogic-toolchain/resource/define" ) -func TestSourcesSet(test *testing.T) { +func TestDefinesUnmarshalText(test *testing.T) { + want := "DEFF=6" + var d define.Defines - fs := flag.NewFlagSet("example", flag.ExitOnError) - fs.Var(&d, "D", "") + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), &d)) - assert.NoError(test, fs.Parse([]string{"-D", "ABC=BAR", "-D", "XYZ", "-D", "X=4", "file"})) - assert.Len(test, d, 3) - assert.Equal(test, "ABC", d[0].Name) - assert.Equal(test, "BAR", d[0].Value) - assert.Equal(test, "XYZ", d[1].Name) - assert.Empty(test, d[1].Value) - assert.Equal(test, "X", d[2].Name) - assert.Equal(test, "4", d[2].Value) + assert.Len(test, d, 1) + assert.Equal(test, "DEFF", d[0].Name) + assert.Equal(test, "6", d[0].Value) + assert.Equal(test, want, d[0].String()) } -func TestSourcesUndefine(test *testing.T) { +func TestDefinesUnmarshalJSON(test *testing.T) { var d define.Defines - fs := flag.NewFlagSet("example", flag.ExitOnError) - fs.Var(&define.Undefines{Defines: &d}, "U", "") + assert.NoError(test, json.Unmarshal([]byte(` ["A=1", { "name": "B" }]`), &d)) - assert.NoError(test, fs.Parse([]string{"-U", "FOO=BAR", "-U", "XYZ", "file"})) assert.Len(test, d, 2) - assert.Equal(test, "FOO", d[0].Name) - assert.Equal(test, "BAR", d[0].Value) - assert.Equal(test, "XYZ", d[1].Name) + + assert.Equal(test, "A", d[0].Name) + assert.Equal(test, "1", d[0].Value) + assert.Equal(test, "A=1", d[0].String()) + + assert.Equal(test, "B", d[1].Name) assert.Empty(test, d[1].Value) + assert.Equal(test, "B", d[1].String()) +} + +func TestDefinesUnmarshalJSONObject(test *testing.T) { + want := "C" + + var d define.Defines + + assert.NoError(test, json.Unmarshal([]byte(` { "name": "`+want+`" } `), &d)) + + assert.Len(test, d, 1) + assert.Equal(test, "C", d[0].String()) + assert.Equal(test, "C", d[0].Name) + assert.Empty(test, d[0].Value) +} + +func TestDefinesUnmarshalJSONNull(test *testing.T) { + var d define.Defines + + assert.NoError(test, json.Unmarshal([]byte(` null `), &d)) + assert.Empty(test, d) +} + +func TestDefinesUnmarshalJSONError(test *testing.T) { + var d define.Defines + + assert.Error(test, json.Unmarshal([]byte(`[5]`), &d)) + assert.Empty(test, d) +} + +func TestDefinesUnmarshalJSONObjectError(test *testing.T) { + var d define.Defines + + assert.Error(test, json.Unmarshal([]byte(`{"name":5}`), &d)) + assert.Empty(test, d) +} + +func TestDefinesUnmarshalJSONInvalid(test *testing.T) { + var d define.Defines + + assert.Error(test, json.Unmarshal([]byte(`true`), &d)) + assert.Empty(test, d) } diff --git a/resource/define/undefines.go b/resource/define/undefines.go deleted file mode 100644 index ff84a72..0000000 --- a/resource/define/undefines.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package define - -// Undefines provides an undefine wrapper around define object. -type Undefines struct { - Defines *Defines -} - -// Strings returns string representation. -func (*Undefines) String() string { - return "" -} - -// Set is called once, in command line order, for each flag present. -func (u *Undefines) Set(value string) error { - *u.Defines = append(*u.Defines, New(value).Undef()) - - return nil -} diff --git a/resource/header/headers.go b/resource/header/headers.go index a3ccbbc..e205310 100644 --- a/resource/header/headers.go +++ b/resource/header/headers.go @@ -54,13 +54,13 @@ func (h *Headers) UnmarshalJSON(data []byte) error { return rterror.New("invalid JSON type") } - sources := []*Header{} + headers := []*Header{} - if err := json.Unmarshal(data, &sources); err != nil { + if err := json.Unmarshal(data, &headers); err != nil { return rterror.New("error occurred while decoding JSON", err) } - *h = sources + *h = headers return nil } -- GitLab From 96d7956491de995345095794050ace520c9e96cf Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Thu, 29 Oct 2020 23:08:24 +0100 Subject: [PATCH 07/12] Added undefine --- resource/object/object.go | 12 ++-- resource/undefine/undefine.go | 71 +++++++++++++++++++++++ resource/undefine/undefine_test.go | 88 ++++++++++++++++++++++++++++ resource/undefine/undefines.go | 65 +++++++++++++++++++++ resource/undefine/undefines_test.go | 89 +++++++++++++++++++++++++++++ 5 files changed, 318 insertions(+), 7 deletions(-) create mode 100644 resource/undefine/undefine.go create mode 100644 resource/undefine/undefine_test.go create mode 100644 resource/undefine/undefines.go create mode 100644 resource/undefine/undefines_test.go diff --git a/resource/object/object.go b/resource/object/object.go index c7a9101..41ec541 100644 --- a/resource/object/object.go +++ b/resource/object/object.go @@ -21,7 +21,6 @@ import ( "gitlab.com/tymonx/xlogic-toolchain/resource/define" "gitlab.com/tymonx/xlogic-toolchain/resource/header" "gitlab.com/tymonx/xlogic-toolchain/resource/include" - "gitlab.com/tymonx/xlogic-toolchain/resource/output" "gitlab.com/tymonx/xlogic-toolchain/resource/source" ) @@ -32,12 +31,11 @@ var gExtension = map[string]bool{ // nolint: gochecknoglobals // Object defines compiled source file or files to object. type Object struct { - Path path.Path `json:"path,omitempty"` - Source source.Sources `json:"source,omitempty"` - Define define.Defines `json:"define,omitempty"` - Header header.Headers `json:"header,omitempty"` - Output output.Outputs `json:"output,omitempty"` - Include include.Includes `json:"include,omitempty"` + Path path.Path `json:"path,omitempty"` + Sources source.Sources `json:"source,omitempty"` + Defines define.Defines `json:"define,omitempty"` + Headers header.Headers `json:"header,omitempty"` + Includes include.Includes `json:"include,omitempty"` } // Is returns true if path is a archive file, otherwise it returns false. diff --git a/resource/undefine/undefine.go b/resource/undefine/undefine.go new file mode 100644 index 0000000..48acae9 --- /dev/null +++ b/resource/undefine/undefine.go @@ -0,0 +1,71 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package undefine + +import ( + "encoding/json" + "strings" + + "gitlab.com/tymonx/go-error/rterror" +) + +// Undefine undefines undefine. +type Undefine struct { + Name string `json:"name,omitempty"` +} + +// New creates a new undefine object. +func New(name string) *Undefine { + return &Undefine{ + Name: strings.TrimSpace(name), + } +} + +// String returns undefine as string. +func (u *Undefine) String() string { + return u.Name +} + +// UnmarshalText decodes text to undefine. +func (u *Undefine) UnmarshalText(data []byte) error { + u.Name = strings.TrimSpace(string(data)) + return nil +} + +// UnmarshalJSON decodes JSON to undefine. +func (u *Undefine) UnmarshalJSON(data []byte) error { + switch data[0] { + case '{': + case '"': + return u.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *u = Undefine{} + return nil + default: + return rterror.New("invalid JSON type") + } + + object := new(struct { + Name string `json:"name"` + }) + + if err := json.Unmarshal(data, object); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + u.Name = strings.TrimSpace(object.Name) + + return nil +} diff --git a/resource/undefine/undefine_test.go b/resource/undefine/undefine_test.go new file mode 100644 index 0000000..6217d5d --- /dev/null +++ b/resource/undefine/undefine_test.go @@ -0,0 +1,88 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implieu. +// See the License for the specific language governing permissions and +// limitations under the License. + +package undefine_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/resource/undefine" +) + +func TestUndefineNew(test *testing.T) { + want := "Name" + + u := undefine.New(want) + + assert.NotNil(test, u) + assert.Equal(test, "Name", u.Name) + assert.Equal(test, want, u.String()) +} + +func TestUndefineString(test *testing.T) { + want := "NAME" + + assert.NotNil(test, want, undefine.New(want).String()) +} + +func TestUndefineUnmarshalText(test *testing.T) { + want := "MYDEF" + + u := new(undefine.Undefine) + + assert.NoError(test, json.Unmarshal([]byte(` " `+want+` " `), u)) + + assert.Equal(test, want, u.String()) + assert.Equal(test, want, u.Name) +} + +func TestUndefineUnmarshalJSONObject(test *testing.T) { + want := "DEFINE" + + u := new(undefine.Undefine) + + assert.NoError(test, json.Unmarshal([]byte(` { "name": "`+want+`" } `), u)) + + assert.Equal(test, want, u.String()) + assert.Equal(test, want, u.Name) +} + +func TestUndefineUnmarshalJSONNull(test *testing.T) { + u := new(undefine.Undefine) + + assert.NoError(test, json.Unmarshal([]byte(` null `), u)) + + assert.Empty(test, u.String()) + assert.Empty(test, u.Name) +} + +func TestUndefineUnmarshalJSONError(test *testing.T) { + u := new(undefine.Undefine) + + assert.Error(test, json.Unmarshal([]byte(`{"name":5}`), u)) + + assert.Empty(test, u.String()) + assert.Empty(test, u.Name) +} + +func TestUndefineUnmarshalJSONInvalid(test *testing.T) { + u := new(undefine.Undefine) + + assert.Error(test, json.Unmarshal([]byte(`true`), u)) + + assert.Empty(test, u.String()) + assert.Empty(test, u.Name) +} diff --git a/resource/undefine/undefines.go b/resource/undefine/undefines.go new file mode 100644 index 0000000..e3651c9 --- /dev/null +++ b/resource/undefine/undefines.go @@ -0,0 +1,65 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package undefine + +import ( + "encoding/json" + + "gitlab.com/tymonx/go-error/rterror" +) + +// Undefines undefines a list of undefines. +type Undefines []*Undefine + +// UnmarshalText decodes text to undefine. +func (u *Undefines) UnmarshalText(data []byte) error { + *u = Undefines{New(string(data))} + + return nil +} + +// UnmarshalJSON decodes JSON to undefine. +func (u *Undefines) UnmarshalJSON(data []byte) error { + switch data[0] { + case '[': + case '{': + object := new(Undefine) + + if err := json.Unmarshal(data, object); err != nil { + return err + } + + *u = Undefines{object} + + return nil + case '"': + return u.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *u = Undefines{} + return nil + default: + return rterror.New("invalid JSON type") + } + + undefines := []*Undefine{} + + if err := json.Unmarshal(data, &undefines); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + *u = undefines + + return nil +} diff --git a/resource/undefine/undefines_test.go b/resource/undefine/undefines_test.go new file mode 100644 index 0000000..4b3756d --- /dev/null +++ b/resource/undefine/undefines_test.go @@ -0,0 +1,89 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package undefine_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/resource/undefine" +) + +func TestUndefinesUnmarshalText(test *testing.T) { + want := "DEFF" + + var u undefine.Undefines + + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), &u)) + + assert.Len(test, u, 1) + assert.Equal(test, want, u[0].Name) + assert.Equal(test, want, u[0].String()) +} + +func TestUndefinesUnmarshalJSON(test *testing.T) { + var u undefine.Undefines + + assert.NoError(test, json.Unmarshal([]byte(` ["A", { "name": "B" }]`), &u)) + + assert.Len(test, u, 2) + + assert.Equal(test, "A", u[0].Name) + assert.Equal(test, "A", u[0].String()) + + assert.Equal(test, "B", u[1].Name) + assert.Equal(test, "B", u[1].String()) +} + +func TestUndefinesUnmarshalJSONObject(test *testing.T) { + want := "C" + + var u undefine.Undefines + + assert.NoError(test, json.Unmarshal([]byte(` { "name": "`+want+`" } `), &u)) + + assert.Len(test, u, 1) + assert.Equal(test, want, u[0].String()) + assert.Equal(test, want, u[0].Name) +} + +func TestUndefinesUnmarshalJSONNull(test *testing.T) { + var u undefine.Undefines + + assert.NoError(test, json.Unmarshal([]byte(` null `), &u)) + assert.Empty(test, u) +} + +func TestUndefinesUnmarshalJSONError(test *testing.T) { + var u undefine.Undefines + + assert.Error(test, json.Unmarshal([]byte(`[5]`), &u)) + assert.Empty(test, u) +} + +func TestUndefinesUnmarshalJSONObjectError(test *testing.T) { + var u undefine.Undefines + + assert.Error(test, json.Unmarshal([]byte(`{"name":5}`), &u)) + assert.Empty(test, u) +} + +func TestUndefinesUnmarshalJSONInvalid(test *testing.T) { + var u undefine.Undefines + + assert.Error(test, json.Unmarshal([]byte(`true`), &u)) + assert.Empty(test, u) +} -- GitLab From 761a428af0b7ec6685be600ce35b7731fd03a79c Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Sat, 31 Oct 2020 20:05:42 +0100 Subject: [PATCH 08/12] Added file type --- path/path.go | 11 ++ path/path_test.go | 35 ++++- path/paths.go | 5 - resource/file/file.go | 130 +++++++++++++++++++ resource/file/file_test.go | 222 ++++++++++++++++++++++++++++++++ resource/file/files.go | 18 +++ resource/file/kind/kind.go | 125 ++++++++++++++++++ resource/file/kind/kind_test.go | 74 +++++++++++ 8 files changed, 613 insertions(+), 7 deletions(-) create mode 100644 resource/file/file.go create mode 100644 resource/file/file_test.go create mode 100644 resource/file/files.go create mode 100644 resource/file/kind/kind.go create mode 100644 resource/file/kind/kind_test.go diff --git a/path/path.go b/path/path.go index c5cb237..f37475b 100644 --- a/path/path.go +++ b/path/path.go @@ -120,6 +120,17 @@ func (p *Path) IsAbsolute() bool { return filepath.IsAbs(p.String()) } +// UnmarshalText decodes text to file path. +func (p *Path) UnmarshalText(data []byte) error { + *p = Path(data) + return nil +} + +// MarshalText encodes file path to text. +func (p *Path) MarshalText() (data []byte, err error) { + return []byte(p.String()), nil +} + // Load loads object fields from file. func (p *Path) Load(object interface{}) (err error) { var data []byte diff --git a/path/path_test.go b/path/path_test.go index 454593d..b9d2997 100644 --- a/path/path_test.go +++ b/path/path_test.go @@ -204,7 +204,7 @@ func TestPathMarshalJSONInvalid(test *testing.T) { assert.Equal(test, []byte(`"`+want+`"`), data) } -func TestPatpDump(test *testing.T) { +func TestPathDump(test *testing.T) { object := &struct { Value int `json:"value"` }{ @@ -214,6 +214,7 @@ func TestPatpDump(test *testing.T) { file, err := ioutil.TempFile("", "tmp*") defer assert.NoError(test, os.Remove(file.Name())) + defer assert.NoError(test, file.Close()) assert.NoError(test, err) @@ -222,7 +223,7 @@ func TestPatpDump(test *testing.T) { assert.NoError(test, p.Dump(object)) } -func TestPatpDumpError(test *testing.T) { +func TestPathDumpError(test *testing.T) { object := &struct { Chan chan struct{} }{} @@ -230,6 +231,7 @@ func TestPatpDumpError(test *testing.T) { file, err := ioutil.TempFile("", "tmp*") defer assert.NoError(test, os.Remove(file.Name())) + defer assert.NoError(test, file.Close()) assert.NoError(test, err) @@ -237,3 +239,32 @@ func TestPatpDumpError(test *testing.T) { assert.Error(test, p.Dump(object)) } + +func TestPathLoad(test *testing.T) { + object := &struct { + Value int `json:"value"` + }{} + + file, err := ioutil.TempFile("", "tmp*") + + defer assert.NoError(test, os.Remove(file.Name())) + defer assert.NoError(test, file.Close()) + + p := path.Path(file.Name()) + + assert.NoError(test, err) + assert.NoError(test, ioutil.WriteFile(file.Name(), []byte(`{ "value": 4 }`), 0600)) + assert.NoError(test, p.Load(&object)) + assert.Equal(test, 4, object.Value) +} + +func TestPathLoadError(test *testing.T) { + object := &struct { + Value int `json:"value"` + }{} + + p := path.Path("invalid") + + assert.Error(test, p.Load(&object)) + assert.Zero(test, object.Value) +} diff --git a/path/paths.go b/path/paths.go index 6fc8693..7fadef2 100644 --- a/path/paths.go +++ b/path/paths.go @@ -16,8 +16,3 @@ package path // Paths defines a list of file paths. type Paths []Path - -// Add adds path. -func (p *Paths) Add(file Path) { - *p = append(*p, file) -} diff --git a/resource/file/file.go b/resource/file/file.go new file mode 100644 index 0000000..9f288e4 --- /dev/null +++ b/resource/file/file.go @@ -0,0 +1,130 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package file + +import ( + "encoding/json" + "io/ioutil" + + "gitlab.com/tymonx/go-error/rterror" + "gitlab.com/tymonx/xlogic-toolchain/path" + "gitlab.com/tymonx/xlogic-toolchain/resource/define" + "gitlab.com/tymonx/xlogic-toolchain/resource/file/kind" + "gitlab.com/tymonx/xlogic-toolchain/resource/header" + "gitlab.com/tymonx/xlogic-toolchain/resource/id" + "gitlab.com/tymonx/xlogic-toolchain/resource/include" + "gitlab.com/tymonx/xlogic-toolchain/resource/undefine" +) + +// Marshal is used only in testing and mocking. +var Marshal = json.Marshal // nolint: gochecknoglobals + +// File defines a generic object that describes input or generated output file. +type File struct { + ID id.ID `json:"id"` + Kind kind.Kind `json:"kind"` + Path path.Path `json:"path"` + Headers header.Headers `json:"header"` + Defines define.Defines `json:"define"` + Includes include.Includes `json:"include"` + Undefines undefine.Undefines `json:"undefine"` + Files Files `json:"file"` +} + +// New creates a new file object. +func New(p path.Path) *File { + return &File{ + ID: id.New(), + Kind: kind.FromPath(p), + Path: p, + } +} + +// Load loads file content. +func (f *File) Load(p path.Path) (err error) { + if k := kind.FromPath(p); (k != kind.JSON) && (k != kind.Unknown) { + f.ID = id.New() + f.Kind = k + f.Path = p + + return nil + } + + var data []byte + + if data, err = ioutil.ReadFile(p.String()); err != nil { + return rterror.New("cannot read file", p, err) + } + + if err := json.Unmarshal(data, f); err != nil { + return rterror.New("cannot decode JSON to file", err) + } + + return nil +} + +// Dump dumps file content. +func (f *File) Dump(p path.Path) (err error) { + // use as a fmt.Stringer + var data []byte + + if data, err = Marshal(f); err != nil { + return rterror.New("cannot encode file to JSON", err) + } + + if err := ioutil.WriteFile(p.String(), data, 0600); err != nil { + return rterror.New("cannot write to file", p, err) + } + + return nil +} + +// UnmarshalText decodes text to file. +func (f *File) UnmarshalText(data []byte) error { + return f.Load(path.Path(data)) +} + +// UnmarshalJSON decides JSON to file. +func (f *File) UnmarshalJSON(data []byte) error { + switch data[0] { + case '{': + case '"': + return f.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *f = File{} + return nil + default: + return rterror.New("invalid JSON type") + } + + object := new(struct { + ID id.ID `json:"id"` + Kind kind.Kind `json:"kind"` + Path path.Path `json:"path"` + Headers header.Headers `json:"header"` + Defines define.Defines `json:"define"` + Includes include.Includes `json:"include"` + Undefines undefine.Undefines `json:"undefine"` + Files Files `json:"file"` + }) + + if err := json.Unmarshal(data, object); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + *f = *object + + return nil +} diff --git a/resource/file/file_test.go b/resource/file/file_test.go new file mode 100644 index 0000000..e8ec08a --- /dev/null +++ b/resource/file/file_test.go @@ -0,0 +1,222 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package file_test + +import ( + "encoding/json" + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/go-error/rterror" + "gitlab.com/tymonx/xlogic-toolchain/path" + "gitlab.com/tymonx/xlogic-toolchain/resource/file" + "gitlab.com/tymonx/xlogic-toolchain/resource/file/kind" +) + +func TestFileNew(test *testing.T) { + want := "dir/file.sv" + + f := file.New(path.Path(want)) + + assert.NotNil(test, f) + assert.Equal(test, want, f.Path.String()) + assert.Equal(test, kind.SystemVerilog, f.Kind) + assert.NotEmpty(test, f.ID) +} + +func TestFileLoad(test *testing.T) { // nolint: dupl + h, err := ioutil.TempFile("", "*.c") + + defer assert.NoError(test, os.Remove(h.Name())) + defer assert.NoError(test, h.Close()) + + f := file.New("") + + assert.NoError(test, err) + assert.NoError(test, ioutil.WriteFile(h.Name(), []byte(`{}`), 0600)) + assert.NoError(test, f.Load(path.Path(h.Name()))) + + assert.Equal(test, h.Name(), f.Path.String()) + assert.Equal(test, kind.C, f.Kind) + assert.NotEmpty(test, f.ID) +} + +func TestFileLoadJSON(test *testing.T) { + h, err := ioutil.TempFile("", "*.json") + + defer assert.NoError(test, os.Remove(h.Name())) + defer assert.NoError(test, h.Close()) + + f := file.New("") + + assert.NoError(test, err) + assert.NoError(test, ioutil.WriteFile(h.Name(), []byte(`{"id": "id", "kind": "object", "path": "file.o"}`), 0600)) + assert.NoError(test, f.Load(path.Path(h.Name()))) + + assert.Equal(test, "file.o", f.Path.String()) + assert.Equal(test, kind.Object, f.Kind) + assert.Equal(test, "id", f.ID.String()) +} + +func TestFileLoadJSONError(test *testing.T) { + h, err := ioutil.TempFile("", "*.json") + + defer assert.NoError(test, os.Remove(h.Name())) + defer assert.NoError(test, h.Close()) + + f := file.New("") + + assert.NoError(test, err) + assert.NoError(test, ioutil.WriteFile(h.Name(), []byte(`{"id": true}`), 0600)) + assert.Error(test, f.Load(path.Path(h.Name()))) + + assert.Empty(test, f.Path) + assert.Equal(test, kind.Unknown, f.Kind) + assert.NotEmpty(test, f.ID) +} + +func TestFileLoadReadError(test *testing.T) { + f := file.New("") + + assert.Error(test, f.Load("invalid")) + + assert.Empty(test, f.Path) + assert.Equal(test, kind.Unknown, f.Kind) + assert.NotEmpty(test, f.ID) +} + +func TestFileLoadUnmarshalError(test *testing.T) { // nolint: dupl + h, err := ioutil.TempFile("", "*.v") + + defer assert.NoError(test, os.Remove(h.Name())) + defer assert.NoError(test, h.Close()) + + f := file.New("") + + assert.NoError(test, err) + assert.NoError(test, ioutil.WriteFile(h.Name(), []byte(`{ "data": 5 }`), 0600)) + assert.NoError(test, f.Load(path.Path(h.Name()))) + + assert.Equal(test, h.Name(), f.Path.String()) + assert.Equal(test, kind.Verilog, f.Kind) + assert.NotEmpty(test, f.ID) +} + +func TestFileDump(test *testing.T) { // nolint: dupl + h, err := ioutil.TempFile("", "*.json") + + defer assert.NoError(test, os.Remove(h.Name())) + defer assert.NoError(test, h.Close()) + + f := file.New("file.o") + + assert.NoError(test, err) + assert.NoError(test, f.Dump(path.Path(h.Name()))) + + object := &struct { + ID string `json:"id"` + Path string `json:"path"` + Kind string `json:"kind"` + }{} + + data, err := ioutil.ReadFile(h.Name()) + + assert.NotNil(test, data) + assert.NoError(test, err) + assert.NoError(test, json.Unmarshal(data, object)) + assert.Equal(test, "file.o", object.Path) + assert.Equal(test, "object", object.Kind) + assert.NotEmpty(test, object.ID) +} + +func TestFileDumpError(test *testing.T) { // nolint: dupl + h, err := ioutil.TempFile("", "*.json") + + defer assert.NoError(test, os.Remove(h.Name())) + defer assert.NoError(test, h.Close()) + + f := file.New("file.o") + + assert.NoError(test, err) + assert.NoError(test, f.Dump(path.Path(h.Name()))) + + object := &struct { + ID string `json:"id"` + Path string `json:"path"` + Kind string `json:"kind"` + }{} + + data, err := ioutil.ReadFile(h.Name()) + + assert.NotNil(test, data) + assert.NoError(test, err) + assert.NoError(test, json.Unmarshal(data, object)) + assert.Equal(test, "file.o", object.Path) + assert.Equal(test, "object", object.Kind) + assert.NotEmpty(test, object.ID) +} + +func TestFileDumpWriteError(test *testing.T) { + d, err := ioutil.TempDir("", "") + + defer assert.NoError(test, os.Remove(d)) + + f := file.New("file.o") + + assert.NoError(test, err) + assert.Error(test, f.Dump(path.Path(d+"/"))) +} + +func TestFileDumpMarshalError(test *testing.T) { + defer func() { + file.Marshal = json.Marshal + }() + + file.Marshal = func(interface{}) ([]byte, error) { + return nil, rterror.New("error") + } + + assert.Error(test, file.New("").Dump("")) +} + +func TestFileUnmarshalText(test *testing.T) { + h, err := ioutil.TempFile("", "*.json") + + defer assert.NoError(test, os.Remove(h.Name())) + defer assert.NoError(test, h.Close()) + + var f file.File + + assert.NoError(test, err) + assert.NoError(test, ioutil.WriteFile(h.Name(), []byte(`{"path": "file.o"}`), 0600)) + assert.NoError(test, json.Unmarshal([]byte(`"`+h.Name()+`"`), &f)) + assert.Equal(test, "file.o", f.Path.String()) +} + +func TestFileUnmarshalNull(test *testing.T) { + var f file.File + + assert.NoError(test, json.Unmarshal([]byte(` null `), &f)) + assert.Empty(test, f) +} + +func TestFileUnmarshalInvalid(test *testing.T) { + var f file.File + + assert.Error(test, json.Unmarshal([]byte(` true `), &f)) + assert.Empty(test, f) +} diff --git a/resource/file/files.go b/resource/file/files.go new file mode 100644 index 0000000..f0c53fa --- /dev/null +++ b/resource/file/files.go @@ -0,0 +1,18 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package file + +// Files defines a list of generic objects that describes input or generated output files. +type Files []*File diff --git a/resource/file/kind/kind.go b/resource/file/kind/kind.go new file mode 100644 index 0000000..3f20f57 --- /dev/null +++ b/resource/file/kind/kind.go @@ -0,0 +1,125 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kind + +import ( + "strings" + + "gitlab.com/tymonx/xlogic-toolchain/path" +) + +// These constants define values for file. +const ( + Unknown Kind = 0 + Object Kind = 1 + Archive Kind = 2 + Library Kind = 3 + Executable Kind = 4 + C Kind = 5 + IP Kind = 6 + Cxx Kind = 7 + TCL Kind = 8 + JSON Kind = 9 + VHDL Kind = 10 + Verilog Kind = 11 + SystemVerilog Kind = 12 +) + +var gToString = map[Kind]string{ // nolint: gochecknoglobals + Unknown: "", + Object: "object", + Archive: "archive", + Library: "library", + Executable: "executable", + C: "c", + IP: "ip", + Cxx: "c++", + TCL: "tcl", + JSON: "json", + VHDL: "vhdl", + Verilog: "verilog", + SystemVerilog: "systemverilog", +} + +var gFromString = map[string]Kind{ // nolint: gochecknoglobals + "": Unknown, + "object": Object, + "archive": Archive, + "library": Library, + "executable": Executable, + "c": C, + "ip": IP, + "c++": Cxx, + "tcl": TCL, + "json": JSON, + "vhdl": VHDL, + "verilog": Verilog, + "systemverilog": SystemVerilog, +} + +var gFromExtension = map[string]Kind{ // nolint: gochecknoglobals + ".c": C, + ".o": Object, + ".a": Archive, + ".lib": Archive, + ".so": Library, + ".dll": Library, + ".exe": Executable, + ".ip": IP, + ".cc": Cxx, + ".cxx": Cxx, + ".cpp": Cxx, + ".c++": Cxx, + ".tcl": TCL, + ".vhd": VHDL, + ".vhdl": VHDL, + ".json": JSON, + ".v": Verilog, + ".sv": SystemVerilog, +} + +// Kind defines file kind. +type Kind int + +// Is returns true if path is a file, otherwise it returns false. +func Is(file path.Path) bool { + return gFromExtension[strings.ToLower(file.Extension())] != Unknown +} + +// FromString returns kind from given string. +func FromString(str string) Kind { + return gFromString[strings.TrimSpace(strings.ToLower(str))] +} + +// FromPath returns kind from given file path. +func FromPath(file path.Path) Kind { + return gFromExtension[strings.ToLower(file.Extension())] +} + +// String returns kind as string. +func (k *Kind) String() string { + return gToString[*k] +} + +// UnmarshalText decodes from text to kind. +func (k *Kind) UnmarshalText(data []byte) error { + *k = FromString(string(data)) + return nil +} + +// MarshalText decodes from kind to text. +func (k *Kind) MarshalText() (data []byte, err error) { + return []byte(k.String()), nil +} diff --git a/resource/file/kind/kind_test.go b/resource/file/kind/kind_test.go new file mode 100644 index 0000000..f72a52c --- /dev/null +++ b/resource/file/kind/kind_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kind_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + + "gitlab.com/tymonx/xlogic-toolchain/resource/file/kind" +) + +func TestKindFromString(test *testing.T) { + assert.Equal(test, kind.C, kind.FromString("c ")) + assert.Equal(test, kind.IP, kind.FromString("IP")) + assert.Equal(test, kind.Cxx, kind.FromString("C++")) + assert.Equal(test, kind.TCL, kind.FromString("tCL")) + assert.Equal(test, kind.VHDL, kind.FromString("Vhdl ")) + assert.Equal(test, kind.Verilog, kind.FromString(" VeRILOG")) + assert.Equal(test, kind.SystemVerilog, kind.FromString(" SystemVERILOG ")) +} + +func TestKindFromPath(test *testing.T) { + assert.Equal(test, kind.C, kind.FromPath("dir/file.c")) + assert.Equal(test, kind.IP, kind.FromPath("dir/file.ip")) + assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.cc")) + assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.cpp")) + assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.cxx")) + assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.c++")) + assert.Equal(test, kind.TCL, kind.FromPath("dir/file.tcl")) + assert.Equal(test, kind.VHDL, kind.FromPath("dir/file.Vhdl")) + assert.Equal(test, kind.Verilog, kind.FromPath("dir/file.V")) + assert.Equal(test, kind.SystemVerilog, kind.FromPath("dir/file.sV")) +} + +func TestKindIs(test *testing.T) { + assert.True(test, kind.Is("dir/file.vhd")) + assert.False(test, kind.Is("dir/dir2")) +} + +func TestKindString(test *testing.T) { + k := kind.FromPath("dir/file.sv") + + assert.Equal(test, "systemverilog", k.String()) +} + +func TestKindUnmarshalJSON(test *testing.T) { + var k kind.Kind + + assert.NoError(test, json.Unmarshal([]byte(` " SystemVerilOg " `), &k)) + assert.Equal(test, kind.SystemVerilog, k) +} + +func TestKindMarshalJSON(test *testing.T) { + k := kind.FromPath("dir/file.v") + + data, err := json.Marshal(&k) + + assert.NoError(test, err) + assert.Equal(test, []byte(`"verilog"`), data) +} -- GitLab From d49f44bcf746bb1962152d8a4590755b1de6e688 Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Sat, 31 Oct 2020 20:29:03 +0100 Subject: [PATCH 09/12] Added file type --- resource/file/kind/kind.go | 20 ++++++++++++++++---- resource/file/kind/kind_test.go | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/resource/file/kind/kind.go b/resource/file/kind/kind.go index 3f20f57..7be2f80 100644 --- a/resource/file/kind/kind.go +++ b/resource/file/kind/kind.go @@ -78,7 +78,9 @@ var gFromExtension = map[string]Kind{ // nolint: gochecknoglobals ".dll": Library, ".exe": Executable, ".ip": IP, + ".C": Cxx, ".cc": Cxx, + ".cp": Cxx, ".cxx": Cxx, ".cpp": Cxx, ".c++": Cxx, @@ -94,8 +96,8 @@ var gFromExtension = map[string]Kind{ // nolint: gochecknoglobals type Kind int // Is returns true if path is a file, otherwise it returns false. -func Is(file path.Path) bool { - return gFromExtension[strings.ToLower(file.Extension())] != Unknown +func Is(p path.Path) bool { + return fromExtension(p) != Unknown } // FromString returns kind from given string. @@ -104,8 +106,8 @@ func FromString(str string) Kind { } // FromPath returns kind from given file path. -func FromPath(file path.Path) Kind { - return gFromExtension[strings.ToLower(file.Extension())] +func FromPath(p path.Path) Kind { + return fromExtension(p) } // String returns kind as string. @@ -123,3 +125,13 @@ func (k *Kind) UnmarshalText(data []byte) error { func (k *Kind) MarshalText() (data []byte, err error) { return []byte(k.String()), nil } + +func fromExtension(p path.Path) Kind { + extension := p.Extension() + + if k, ok := gFromExtension[extension]; ok { + return k + } + + return gFromExtension[strings.ToLower(extension)] +} diff --git a/resource/file/kind/kind_test.go b/resource/file/kind/kind_test.go index f72a52c..e09348f 100644 --- a/resource/file/kind/kind_test.go +++ b/resource/file/kind/kind_test.go @@ -36,6 +36,7 @@ func TestKindFromString(test *testing.T) { func TestKindFromPath(test *testing.T) { assert.Equal(test, kind.C, kind.FromPath("dir/file.c")) assert.Equal(test, kind.IP, kind.FromPath("dir/file.ip")) + assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.C")) assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.cc")) assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.cpp")) assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.cxx")) -- GitLab From f820daa0c000cb0f9f14a4804b88a27e0c857897 Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Sat, 31 Oct 2020 22:28:25 +0100 Subject: [PATCH 10/12] Added file type --- resource/file/file.go | 4 ++ resource/file/files.go | 54 +++++++++++++++++++ resource/file/files_test.go | 101 ++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 resource/file/files_test.go diff --git a/resource/file/file.go b/resource/file/file.go index 9f288e4..9ccb125 100644 --- a/resource/file/file.go +++ b/resource/file/file.go @@ -126,5 +126,9 @@ func (f *File) UnmarshalJSON(data []byte) error { *f = *object + if f.Kind == kind.Unknown { + f.Kind = kind.FromPath(f.Path) + } + return nil } diff --git a/resource/file/files.go b/resource/file/files.go index f0c53fa..3af861e 100644 --- a/resource/file/files.go +++ b/resource/file/files.go @@ -14,5 +14,59 @@ package file +import ( + "encoding/json" + + "gitlab.com/tymonx/go-error/rterror" + "gitlab.com/tymonx/xlogic-toolchain/path" +) + // Files defines a list of generic objects that describes input or generated output files. type Files []*File + +// UnmarshalText decodes text to file path. +func (f *Files) UnmarshalText(data []byte) error { + object := new(File) + + if err := object.Load(path.Path(data)); err != nil { + return rterror.New("error occurred while decoding text", string(data), err) + } + + *f = Files{object} + + return nil +} + +// UnmarshalJSON decodes JSON to file path. +func (f *Files) UnmarshalJSON(data []byte) error { + switch data[0] { + case '[': + case '{': + object := new(File) + + if err := json.Unmarshal(data, object); err != nil { + return err + } + + *f = Files{object} + + return nil + case '"': + return f.UnmarshalText(data[1 : len(data)-1]) + case 'n': + *f = Files{} + return nil + default: + return rterror.New("invalid JSON type") + } + + files := []*File{} + + if err := json.Unmarshal(data, &files); err != nil { + return rterror.New("error occurred while decoding JSON", err) + } + + *f = files + + return nil +} diff --git a/resource/file/files_test.go b/resource/file/files_test.go new file mode 100644 index 0000000..321bdfa --- /dev/null +++ b/resource/file/files_test.go @@ -0,0 +1,101 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, foftware +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package file_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/resource/file" + "gitlab.com/tymonx/xlogic-toolchain/resource/file/kind" +) + +func TestFilesUnmarshalText(test *testing.T) { + want := "dir/file.c++" + + var f file.Files + + assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), &f)) + + assert.Len(test, f, 1) + assert.Equal(test, kind.Cxx, f[0].Kind) + assert.Equal(test, "c++", f[0].Kind.String()) + assert.Equal(test, want, f[0].Path.String()) +} + +func TestFilesUnmarshalTextError(test *testing.T) { + var f file.Files + + assert.Error(test, json.Unmarshal([]byte(` "invalid" `), &f)) + assert.Empty(test, f) +} + +func TestFilesUnmarshalJSON(test *testing.T) { + var f file.Files + + assert.NoError(test, json.Unmarshal([]byte(` ["dir/file.c", { "path": "file.tcl" }]`), &f)) + + assert.Len(test, f, 2) + + assert.Equal(test, kind.C, f[0].Kind) + assert.Equal(test, "c", f[0].Kind.String()) + assert.Equal(test, "dir/file.c", f[0].Path.String()) + + assert.Equal(test, kind.TCL, f[1].Kind) + assert.Equal(test, "tcl", f[1].Kind.String()) + assert.Equal(test, "file.tcl", f[1].Path.String()) +} + +func TestFilesUnmarshalJSONObject(test *testing.T) { + want := "dir/file.json" + + var f file.Files + + assert.NoError(test, json.Unmarshal([]byte(` { "path": "`+want+`" } `), &f)) + + assert.Len(test, f, 1) + assert.Equal(test, want, f[0].Path.String()) + assert.Equal(test, kind.JSON, f[0].Kind) + assert.Equal(test, "json", f[0].Kind.String()) +} + +func TestFilesUnmarshalJSONNull(test *testing.T) { + var f file.Files + + assert.NoError(test, json.Unmarshal([]byte(` null `), &f)) + assert.Empty(test, f) +} + +func TestFilesUnmarshalJSONError(test *testing.T) { + var f file.Files + + assert.Error(test, json.Unmarshal([]byte(`[5]`), &f)) + assert.Empty(test, f) +} + +func TestFilesUnmarshalJSONObjectError(test *testing.T) { + var f file.Files + + assert.Error(test, json.Unmarshal([]byte(`{"path":5}`), &f)) + assert.Empty(test, f) +} + +func TestFilesUnmarshalJSONInvalid(test *testing.T) { + var f file.Files + + assert.Error(test, json.Unmarshal([]byte(`true`), &f)) + assert.Empty(test, f) +} -- GitLab From 0473c7237278279fa698404f42c91a5b8afd4a7e Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Sun, 1 Nov 2020 17:43:00 +0100 Subject: [PATCH 11/12] Working compiler --- arguments/arguments.go | 84 ++++++ cmd/xlogic-compiler/main.go | 208 ++------------- compiler/compiler.go | 14 +- {resource/define => define}/define.go | 0 {resource/define => define}/define_test.go | 2 +- {resource/define => define}/defines.go | 8 +- {resource/define => define}/defines_test.go | 2 +- docker-run.sh | 48 ---- {resource/file => file}/file.go | 12 +- {resource/file => file}/file_test.go | 4 +- {resource/file => file}/files.go | 8 +- {resource/file => file}/files_test.go | 4 +- {resource/file => file}/kind/kind.go | 0 {resource/file => file}/kind/kind_test.go | 2 +- go.mod | 1 + go.sum | 7 + {resource/header => header}/header.go | 2 +- {resource/header => header}/header_test.go | 4 +- {resource/header => header}/headers.go | 8 +- {resource/header => header}/headers_test.go | 4 +- {resource/header => header}/kind/kind.go | 0 {resource/header => header}/kind/kind_test.go | 2 +- {resource/id => id}/id.go | 0 {resource/id => id}/id_test.go | 2 +- {resource/id => id}/id_utils_test.go | 0 {resource/include => include}/include.go | 0 {resource/include => include}/include_test.go | 2 +- {resource/include => include}/includes.go | 8 +- .../include => include}/includes_test.go | 2 +- mode/mode.go | 73 ++++++ mode/mode_test.go | 51 ++++ option/option.go | 103 -------- resource/archive/acrhives.go | 18 -- resource/archive/archive.go | 45 ---- resource/executable/executable.go | 57 ----- resource/kind/kind.go | 87 ------- resource/kind/kind_test.go | 54 ---- resource/library/libraries.go | 18 -- resource/library/library.go | 55 ---- resource/object/object.go | 51 ---- resource/object/objects.go | 18 -- resource/output/kind/kind.go | 94 ------- resource/output/kind/kind_test.go | 58 ----- resource/output/metadata/metadata.go | 18 -- resource/output/output.go | 36 --- resource/output/outputs.go | 18 -- resource/resource.go | 242 ------------------ resource/resources.go | 18 -- resource/source/kind/kind.go | 108 -------- resource/source/kind/kind_test.go | 74 ------ resource/source/source.go | 87 ------- resource/source/source_test.go | 101 -------- resource/source/sources.go | 66 ----- resource/source/sources_test.go | 94 ------- {resource/undefine => undefine}/undefine.go | 0 .../undefine => undefine}/undefine_test.go | 2 +- {resource/undefine => undefine}/undefines.go | 8 +- .../undefine => undefine}/undefines_test.go | 2 +- 58 files changed, 293 insertions(+), 1801 deletions(-) create mode 100644 arguments/arguments.go rename {resource/define => define}/define.go (100%) rename {resource/define => define}/define_test.go (97%) rename {resource/define => define}/defines.go (93%) rename {resource/define => define}/defines_test.go (97%) delete mode 100755 docker-run.sh rename {resource/file => file}/file.go (90%) rename {resource/file => file}/file_test.go (98%) rename {resource/file => file}/files.go (95%) rename {resource/file => file}/files_test.go (95%) rename {resource/file => file}/kind/kind.go (100%) rename {resource/file => file}/kind/kind_test.go (97%) rename {resource/header => header}/header.go (97%) rename {resource/header => header}/header_test.go (95%) rename {resource/header => header}/headers.go (93%) rename {resource/header => header}/headers_test.go (95%) rename {resource/header => header}/kind/kind.go (100%) rename {resource/header => header}/kind/kind_test.go (97%) rename {resource/id => id}/id.go (100%) rename {resource/id => id}/id_test.go (95%) rename {resource/id => id}/id_utils_test.go (100%) rename {resource/include => include}/include.go (100%) rename {resource/include => include}/include_test.go (97%) rename {resource/include => include}/includes.go (92%) rename {resource/include => include}/includes_test.go (97%) create mode 100644 mode/mode.go create mode 100644 mode/mode_test.go delete mode 100644 option/option.go delete mode 100644 resource/archive/acrhives.go delete mode 100644 resource/archive/archive.go delete mode 100644 resource/executable/executable.go delete mode 100644 resource/kind/kind.go delete mode 100644 resource/kind/kind_test.go delete mode 100644 resource/library/libraries.go delete mode 100644 resource/library/library.go delete mode 100644 resource/object/object.go delete mode 100644 resource/object/objects.go delete mode 100644 resource/output/kind/kind.go delete mode 100644 resource/output/kind/kind_test.go delete mode 100644 resource/output/metadata/metadata.go delete mode 100644 resource/output/output.go delete mode 100644 resource/output/outputs.go delete mode 100644 resource/resource.go delete mode 100644 resource/resources.go delete mode 100644 resource/source/kind/kind.go delete mode 100644 resource/source/kind/kind_test.go delete mode 100644 resource/source/source.go delete mode 100644 resource/source/source_test.go delete mode 100644 resource/source/sources.go delete mode 100644 resource/source/sources_test.go rename {resource/undefine => undefine}/undefine.go (100%) rename {resource/undefine => undefine}/undefine_test.go (97%) rename {resource/undefine => undefine}/undefines.go (92%) rename {resource/undefine => undefine}/undefines_test.go (97%) diff --git a/arguments/arguments.go b/arguments/arguments.go new file mode 100644 index 0000000..f28634d --- /dev/null +++ b/arguments/arguments.go @@ -0,0 +1,84 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arguments + +import ( + "errors" + "os" + "path/filepath" + + "github.com/alexflint/go-arg" + "gitlab.com/tymonx/go-error/rterror" + "gitlab.com/tymonx/xlogic-toolchain/define" + "gitlab.com/tymonx/xlogic-toolchain/file" + "gitlab.com/tymonx/xlogic-toolchain/header" + "gitlab.com/tymonx/xlogic-toolchain/include" + "gitlab.com/tymonx/xlogic-toolchain/mode" + "gitlab.com/tymonx/xlogic-toolchain/path" + "gitlab.com/tymonx/xlogic-toolchain/undefine" +) + +// These constants define default values for compiler arguments. +const ( + DefaultOutput = "output.json" + DefaultMode = mode.Executable + DefaultProgramName = "xlogic-compiler" +) + +// Arguments defines compiler arguments. +type Arguments struct { + Append bool `arg:"-a,--append" help:"Append file"` + Mode mode.Mode `arg:"-m,--mode" help:"Compiler mode: object, archive, library, executable" default:"executable"` + Output path.Path `arg:"-o,--output" help:"Place output in file" default:"output.json" placeholder:"FILE"` + Defines []define.Define `arg:"-D,--define,separate" help:"Set preprocessor define" placeholder:"NAME[=VALUE]"` + Undefines []undefine.Undefine `arg:"-U,--undefine,separate" help:"Unset preprocessor define" placeholder:"NAME"` + Headers []header.Header `arg:"-H,--header,separate" help:"Include header file" placeholder:"FILE"` + Includes []include.Include `arg:"-I,--include,separate" help:"Directory to search for includes" placeholder:"DIR"` + Files []file.File `arg:"positional" help:"Input files" placeholder:"FILE"` +} + +// New creates a new compiler arguments object. +func New() *Arguments { + return &Arguments{ + Mode: DefaultMode, + Output: DefaultOutput, + } +} + +// Parse parses arguments. +func (a *Arguments) Parse(args ...string) (err error) { + var parser *arg.Parser + + config := arg.Config{} + + if len(args) == 0 { + args = os.Args[1:] + config.Program = filepath.Base(os.Args[0]) + } else { + config.Program = DefaultProgramName + } + + if parser, err = arg.NewParser(arg.Config{}, a); err != nil { + return rterror.New("error occurred while creating parser", err) + } + + if err = parser.Parse(args); errors.Is(err, arg.ErrHelp) { + parser.WriteHelp(os.Stdout) + } else if err != nil { + return rterror.New("error occurred while parsing arguments", err) + } + + return nil +} diff --git a/cmd/xlogic-compiler/main.go b/cmd/xlogic-compiler/main.go index 9e5d8e3..550ec90 100644 --- a/cmd/xlogic-compiler/main.go +++ b/cmd/xlogic-compiler/main.go @@ -15,199 +15,45 @@ package main import ( - "flag" - "fmt" - "os" - "path/filepath" - - "gitlab.com/tymonx/xlogic-toolchain/cerr" - "gitlab.com/tymonx/xlogic-toolchain/option" - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource" - "gitlab.com/tymonx/xlogic-toolchain/resource/kind" + "gitlab.com/tymonx/xlogic-toolchain/arguments" + "gitlab.com/tymonx/xlogic-toolchain/file" + "gitlab.com/tymonx/xlogic-toolchain/file/kind" + "gitlab.com/tymonx/xlogic-toolchain/mode" ) -func usage(f *flag.FlagSet) { - fmt.Println("Usage:", filepath.Base(os.Args[0])) - fmt.Println(f.Name()) - fmt.Println() - - fmt.Println("Options:") - f.PrintDefaults() -} - -func createObject(opt *option.Option, args []string) (r *resource.Resource, err error) { - r = resource.New(kind.Object) - o := r.Object() - - o.Header = opt.Headers - o.Define = opt.Defines - o.Include = opt.Includes - - for _, arg := range args { - var res *resource.Resource - - if res, err = resource.Load(path.Path(arg)); err != nil { - return nil, err - } - - switch res.Kind { - case kind.Source: - o.Source = append(o.Source, res.Source()) - default: - return nil, cerr.InvalidArgument - } - } - - return r, nil -} - -func createArchive(opt *option.Option, args []string) (r *resource.Resource, err error) { - r = resource.New(kind.Archive) - - if opt.Append { - if erro := r.Load(opt.Output); erro != nil { - return nil, erro - } - } - - a := r.Archive() - - for _, arg := range args { - var res *resource.Resource - - if res, err = resource.Load(path.Path(arg)); err != nil { - return nil, err - } - - switch res.Kind { - case kind.Object: - a.Object = append(a.Object, res.Object()) - default: - return nil, cerr.InvalidArgument - } - } - - return r, nil -} - -func createLibrary(opt *option.Option, args []string) (r *resource.Resource, err error) { - r = resource.New(kind.Library) - l := r.Library() - - l.Header = opt.Headers - l.Define = opt.Defines - l.Include = opt.Includes - - for _, arg := range args { - var res *resource.Resource - - if res, err = resource.Load(path.Path(arg)); err != nil { - return nil, err - } - - switch res.Kind { - case kind.Source: - l.Source = append(l.Source, res.Source()) - case kind.Object: - l.Object = append(l.Object, res.Object()) - case kind.Archive: - l.Archive = append(l.Archive, res.Archive()) - default: - return nil, cerr.InvalidArgument - } - } - - return r, nil -} - -func createExecutable(opt *option.Option, args []string) (r *resource.Resource, err error) { - r = resource.New(kind.Executable) - e := r.Executable() - - e.Header = opt.Headers - e.Define = opt.Defines - e.Include = opt.Includes - - for _, arg := range args { - var res *resource.Resource - - if res, err = resource.Load(path.Path(arg)); err != nil { - return nil, err - } - - switch res.Kind { - case kind.Source: - e.Source = append(e.Source, res.Source()) - case kind.Object: - e.Object = append(e.Object, res.Object()) - case kind.Archive: - e.Archive = append(e.Archive, res.Archive()) - case kind.Library: - e.Library = append(e.Library, res.Library()) - default: - return nil, cerr.InvalidArgument - } - } - - return r, nil -} - -func createOutput(opt *option.Option, args []string) (r *resource.Resource, err error) { - if opt.Compile { - if r, err = createObject(opt, args); err != nil { - return nil, err - } +func main() { + args := arguments.New() - return r, nil + if err := args.Parse(); err != nil { + panic(err) } - if opt.Static { - if r, err = createArchive(opt, args); err != nil { - return nil, err - } - - return r, nil - } + output := file.New(args.Output) - if opt.Shared { - if r, err = createLibrary(opt, args); err != nil { - return nil, err + if args.Append { + if err := output.Load(args.Output); err != nil { + panic(err) } - - return r, nil } - if r, err = createExecutable(opt, args); err != nil { - return nil, err + switch args.Mode { + case mode.Object: + output.Kind = kind.Object + case mode.Archive: + output.Kind = kind.Archive + case mode.Library: + output.Kind = kind.Library + case mode.Executable: + output.Kind = kind.Executable } - return r, nil -} - -func main() { - var r *resource.Resource - - f := flag.NewFlagSet("HDL compiler wrapper", flag.ExitOnError) - - opt := option.New().FlagSet(f) - - if err := f.Parse(os.Args[1:]); err != nil { - panic(err) - } - - if opt.Help { - usage(f) - return - } - - var err error - - if r, err = createOutput(opt, f.Args()); err != nil { - panic(err) - } + output.Files = append(output.Files, args.Files...) + output.Defines = append(output.Defines, args.Defines...) + output.Headers = append(output.Headers, args.Headers...) + output.Includes = append(output.Includes, args.Includes...) + output.Undefines = append(output.Undefines, args.Undefines...) - if err := r.Dump(opt.Output); err != nil { + if err := output.Dump(args.Output); err != nil { panic(err) } } diff --git a/compiler/compiler.go b/compiler/compiler.go index 7fa743a..bd8c3dc 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -15,18 +15,16 @@ package compiler import ( - "gitlab.com/tymonx/xlogic-toolchain/resource/archive" - "gitlab.com/tymonx/xlogic-toolchain/resource/executable" - "gitlab.com/tymonx/xlogic-toolchain/resource/library" - "gitlab.com/tymonx/xlogic-toolchain/resource/object" + "gitlab.com/tymonx/xlogic-toolchain/file" ) +// Compiler defines a generic compiler interface. type Compiler interface { - CreateObject(*object.Object) error + CreateObject(f *file.File) error - CreateArchive(*archive.Archive) error + CreateArchive(f *file.File) error - CreateLibrary(*library.Library) error + CreateLibrary(f *file.File) error - CreateExecutable(*executable.Executable) error + CreateExecutable(f *file.File) error } diff --git a/resource/define/define.go b/define/define.go similarity index 100% rename from resource/define/define.go rename to define/define.go diff --git a/resource/define/define_test.go b/define/define_test.go similarity index 97% rename from resource/define/define_test.go rename to define/define_test.go index bb350ee..5d62c49 100644 --- a/resource/define/define_test.go +++ b/define/define_test.go @@ -19,7 +19,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/define" + "gitlab.com/tymonx/xlogic-toolchain/define" ) func TestDefineNew(test *testing.T) { diff --git a/resource/define/defines.go b/define/defines.go similarity index 93% rename from resource/define/defines.go rename to define/defines.go index 238a067..a3abbbc 100644 --- a/resource/define/defines.go +++ b/define/defines.go @@ -21,11 +21,11 @@ import ( ) // Defines defines a list of defines. -type Defines []*Define +type Defines []Define // UnmarshalText decodes text to define. func (d *Defines) UnmarshalText(data []byte) error { - *d = Defines{New(string(data))} + *d = Defines{*New(string(data))} return nil } @@ -41,7 +41,7 @@ func (d *Defines) UnmarshalJSON(data []byte) error { return err } - *d = Defines{object} + *d = Defines{*object} return nil case '"': @@ -53,7 +53,7 @@ func (d *Defines) UnmarshalJSON(data []byte) error { return rterror.New("invalid JSON type") } - defines := []*Define{} + defines := []Define{} if err := json.Unmarshal(data, &defines); err != nil { return rterror.New("error occurred while decoding JSON", err) diff --git a/resource/define/defines_test.go b/define/defines_test.go similarity index 97% rename from resource/define/defines_test.go rename to define/defines_test.go index 007f41f..1b36ed3 100644 --- a/resource/define/defines_test.go +++ b/define/defines_test.go @@ -19,7 +19,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/define" + "gitlab.com/tymonx/xlogic-toolchain/define" ) func TestDefinesUnmarshalText(test *testing.T) { diff --git a/docker-run.sh b/docker-run.sh deleted file mode 100755 index eb7c996..0000000 --- a/docker-run.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env sh -# -# Copyright 2020 Tymoteusz Blazejczyk -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Exit on error -set -e - -# Create a temporary directory for all downloaded Go modules. To have -# the correct file mode permissions with proper user and group, -# this directory must be created before running the docker run command -# with the --volume argument. Otherwise, docker will create directory -# for us with directory properties from container. Mostly of time it is -# unwanted root:root -mkdir -p /tmp/go/ - -# Run Docker image as container. Mount current working directory to container. -# This will allow all commands from Docker to have access to files and -# directories under current working directory, mostly of time it is a project -# workspace. All created files and directories will have proper mode file -# permissions from current user who invokes this script -docker run \ - --rm \ - --tty \ - --interactive \ - --user "$(id -u):$(id -g)" \ - --volume "$(pwd):$(pwd)" \ - --volume "/tmp/:/tmp/" \ - --volume "/tmp/go/:/go/" \ - --volume "/etc/group:/etc/group:ro" \ - --volume "/etc/passwd:/etc/passwd:ro" \ - --workdir "$(pwd)" \ - --publish "${GODOC_PORT:-6060}:6060" \ - --entrypoint /bin/bash \ - --security-opt=label:disable \ - "registry.gitlab.com/tymonx/docker-go:1.14.3" \ - ${@:+-c "$*"} diff --git a/resource/file/file.go b/file/file.go similarity index 90% rename from resource/file/file.go rename to file/file.go index 9ccb125..15b5674 100644 --- a/resource/file/file.go +++ b/file/file.go @@ -19,13 +19,13 @@ import ( "io/ioutil" "gitlab.com/tymonx/go-error/rterror" + "gitlab.com/tymonx/xlogic-toolchain/define" + "gitlab.com/tymonx/xlogic-toolchain/file/kind" + "gitlab.com/tymonx/xlogic-toolchain/header" + "gitlab.com/tymonx/xlogic-toolchain/id" + "gitlab.com/tymonx/xlogic-toolchain/include" "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/define" - "gitlab.com/tymonx/xlogic-toolchain/resource/file/kind" - "gitlab.com/tymonx/xlogic-toolchain/resource/header" - "gitlab.com/tymonx/xlogic-toolchain/resource/id" - "gitlab.com/tymonx/xlogic-toolchain/resource/include" - "gitlab.com/tymonx/xlogic-toolchain/resource/undefine" + "gitlab.com/tymonx/xlogic-toolchain/undefine" ) // Marshal is used only in testing and mocking. diff --git a/resource/file/file_test.go b/file/file_test.go similarity index 98% rename from resource/file/file_test.go rename to file/file_test.go index e8ec08a..ae0ed82 100644 --- a/resource/file/file_test.go +++ b/file/file_test.go @@ -22,9 +22,9 @@ import ( "github.com/stretchr/testify/assert" "gitlab.com/tymonx/go-error/rterror" + "gitlab.com/tymonx/xlogic-toolchain/file" + "gitlab.com/tymonx/xlogic-toolchain/file/kind" "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/file" - "gitlab.com/tymonx/xlogic-toolchain/resource/file/kind" ) func TestFileNew(test *testing.T) { diff --git a/resource/file/files.go b/file/files.go similarity index 95% rename from resource/file/files.go rename to file/files.go index 3af861e..90c760c 100644 --- a/resource/file/files.go +++ b/file/files.go @@ -22,7 +22,7 @@ import ( ) // Files defines a list of generic objects that describes input or generated output files. -type Files []*File +type Files []File // UnmarshalText decodes text to file path. func (f *Files) UnmarshalText(data []byte) error { @@ -32,7 +32,7 @@ func (f *Files) UnmarshalText(data []byte) error { return rterror.New("error occurred while decoding text", string(data), err) } - *f = Files{object} + *f = Files{*object} return nil } @@ -48,7 +48,7 @@ func (f *Files) UnmarshalJSON(data []byte) error { return err } - *f = Files{object} + *f = Files{*object} return nil case '"': @@ -60,7 +60,7 @@ func (f *Files) UnmarshalJSON(data []byte) error { return rterror.New("invalid JSON type") } - files := []*File{} + files := []File{} if err := json.Unmarshal(data, &files); err != nil { return rterror.New("error occurred while decoding JSON", err) diff --git a/resource/file/files_test.go b/file/files_test.go similarity index 95% rename from resource/file/files_test.go rename to file/files_test.go index 321bdfa..b2833fa 100644 --- a/resource/file/files_test.go +++ b/file/files_test.go @@ -19,8 +19,8 @@ import ( "testing" "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/file" - "gitlab.com/tymonx/xlogic-toolchain/resource/file/kind" + "gitlab.com/tymonx/xlogic-toolchain/file" + "gitlab.com/tymonx/xlogic-toolchain/file/kind" ) func TestFilesUnmarshalText(test *testing.T) { diff --git a/resource/file/kind/kind.go b/file/kind/kind.go similarity index 100% rename from resource/file/kind/kind.go rename to file/kind/kind.go diff --git a/resource/file/kind/kind_test.go b/file/kind/kind_test.go similarity index 97% rename from resource/file/kind/kind_test.go rename to file/kind/kind_test.go index e09348f..717580c 100644 --- a/resource/file/kind/kind_test.go +++ b/file/kind/kind_test.go @@ -20,7 +20,7 @@ import ( "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/file/kind" + "gitlab.com/tymonx/xlogic-toolchain/file/kind" ) func TestKindFromString(test *testing.T) { diff --git a/go.mod b/go.mod index c74305c..297d40e 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ module gitlab.com/tymonx/xlogic-toolchain go 1.14 require ( + github.com/alexflint/go-arg v1.3.0 github.com/stretchr/testify v1.6.1 gitlab.com/tymonx/go-error v1.1.0 ) diff --git a/go.sum b/go.sum index 5298066..aa3c1fd 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,15 @@ +github.com/alexflint/go-arg v1.3.0 h1:UfldqSdFWeLtoOuVRosqofU4nmhI1pYEbT4ZFS34Bdo= +github.com/alexflint/go-arg v1.3.0/go.mod h1:9iRbDxne7LcR/GSvEr7ma++GLpdIU1zrghf2y2768kM= +github.com/alexflint/go-scalar v1.0.0 h1:NGupf1XV/Xb04wXskDFzS0KWOLH632W/EO4fAFi+A70= +github.com/alexflint/go-scalar v1.0.0/go.mod h1:GpHzbCOZXEKMEcygYQ5n/aa4Aq84zbxjy3MxYW0gjYw= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= gitlab.com/tymonx/go-error v1.1.0 h1:ynB2GC1Hw3pVhDAoAeAiMmSDBtoM0OXYffWrRIGmDOE= diff --git a/resource/header/header.go b/header/header.go similarity index 97% rename from resource/header/header.go rename to header/header.go index 8e54258..0159c41 100644 --- a/resource/header/header.go +++ b/header/header.go @@ -18,8 +18,8 @@ import ( "encoding/json" "gitlab.com/tymonx/go-error/rterror" + "gitlab.com/tymonx/xlogic-toolchain/header/kind" "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/header/kind" ) // Header defines single header file. diff --git a/resource/header/header_test.go b/header/header_test.go similarity index 95% rename from resource/header/header_test.go rename to header/header_test.go index 3e34751..0c8af2b 100644 --- a/resource/header/header_test.go +++ b/header/header_test.go @@ -19,9 +19,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/header" + "gitlab.com/tymonx/xlogic-toolchain/header/kind" "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/header" - "gitlab.com/tymonx/xlogic-toolchain/resource/header/kind" ) func TestHeaderNew(test *testing.T) { diff --git a/resource/header/headers.go b/header/headers.go similarity index 93% rename from resource/header/headers.go rename to header/headers.go index e205310..5924934 100644 --- a/resource/header/headers.go +++ b/header/headers.go @@ -22,11 +22,11 @@ import ( ) // Headers defines a list of header files. -type Headers []*Header +type Headers []Header // UnmarshalText decodes text to header file path. func (h *Headers) UnmarshalText(data []byte) error { - *h = Headers{New(path.Path(data))} + *h = Headers{*New(path.Path(data))} return nil } @@ -42,7 +42,7 @@ func (h *Headers) UnmarshalJSON(data []byte) error { return err } - *h = Headers{object} + *h = Headers{*object} return nil case '"': @@ -54,7 +54,7 @@ func (h *Headers) UnmarshalJSON(data []byte) error { return rterror.New("invalid JSON type") } - headers := []*Header{} + headers := []Header{} if err := json.Unmarshal(data, &headers); err != nil { return rterror.New("error occurred while decoding JSON", err) diff --git a/resource/header/headers_test.go b/header/headers_test.go similarity index 95% rename from resource/header/headers_test.go rename to header/headers_test.go index e1262a6..c97d984 100644 --- a/resource/header/headers_test.go +++ b/header/headers_test.go @@ -19,8 +19,8 @@ import ( "testing" "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/header" - "gitlab.com/tymonx/xlogic-toolchain/resource/header/kind" + "gitlab.com/tymonx/xlogic-toolchain/header" + "gitlab.com/tymonx/xlogic-toolchain/header/kind" ) func TestHeadersUnmarshalText(test *testing.T) { diff --git a/resource/header/kind/kind.go b/header/kind/kind.go similarity index 100% rename from resource/header/kind/kind.go rename to header/kind/kind.go diff --git a/resource/header/kind/kind_test.go b/header/kind/kind_test.go similarity index 97% rename from resource/header/kind/kind_test.go rename to header/kind/kind_test.go index 06c1d58..cb3793f 100644 --- a/resource/header/kind/kind_test.go +++ b/header/kind/kind_test.go @@ -20,7 +20,7 @@ import ( "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/header/kind" + "gitlab.com/tymonx/xlogic-toolchain/header/kind" ) func TestKindFromString(test *testing.T) { diff --git a/resource/id/id.go b/id/id.go similarity index 100% rename from resource/id/id.go rename to id/id.go diff --git a/resource/id/id_test.go b/id/id_test.go similarity index 95% rename from resource/id/id_test.go rename to id/id_test.go index e191f6a..fbcaed5 100644 --- a/resource/id/id_test.go +++ b/id/id_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/id" + "gitlab.com/tymonx/xlogic-toolchain/id" ) func TestIDGenerate(test *testing.T) { diff --git a/resource/id/id_utils_test.go b/id/id_utils_test.go similarity index 100% rename from resource/id/id_utils_test.go rename to id/id_utils_test.go diff --git a/resource/include/include.go b/include/include.go similarity index 100% rename from resource/include/include.go rename to include/include.go diff --git a/resource/include/include_test.go b/include/include_test.go similarity index 97% rename from resource/include/include_test.go rename to include/include_test.go index e91a64d..f57a9a7 100644 --- a/resource/include/include_test.go +++ b/include/include_test.go @@ -19,8 +19,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/include" "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/include" ) func TestIncludeNew(test *testing.T) { diff --git a/resource/include/includes.go b/include/includes.go similarity index 92% rename from resource/include/includes.go rename to include/includes.go index e904b15..cc58484 100644 --- a/resource/include/includes.go +++ b/include/includes.go @@ -22,11 +22,11 @@ import ( ) // Includes defines a list of include directory paths. -type Includes []*Include +type Includes []Include // UnmarshalText decodes text to include directory path. func (i *Includes) UnmarshalText(data []byte) error { - *i = Includes{New(path.Path(data))} + *i = Includes{*New(path.Path(data))} return nil } @@ -42,7 +42,7 @@ func (i *Includes) UnmarshalJSON(data []byte) error { return err } - *i = Includes{object} + *i = Includes{*object} return nil case '"': @@ -54,7 +54,7 @@ func (i *Includes) UnmarshalJSON(data []byte) error { return rterror.New("invalid JSON type") } - includes := []*Include{} + includes := []Include{} if err := json.Unmarshal(data, &includes); err != nil { return rterror.New("error occurred while decoding JSON", err) diff --git a/resource/include/includes_test.go b/include/includes_test.go similarity index 97% rename from resource/include/includes_test.go rename to include/includes_test.go index 5cc9c28..180afa6 100644 --- a/resource/include/includes_test.go +++ b/include/includes_test.go @@ -19,7 +19,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/include" + "gitlab.com/tymonx/xlogic-toolchain/include" ) func TestIncludesUnmarshalText(test *testing.T) { diff --git a/mode/mode.go b/mode/mode.go new file mode 100644 index 0000000..fb69885 --- /dev/null +++ b/mode/mode.go @@ -0,0 +1,73 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mode + +import ( + "strings" + + "gitlab.com/tymonx/go-error/rterror" +) + +// These constants define compiler modes. +const ( + Executable Mode = 0 + Library Mode = 1 + Archive Mode = 2 + Object Mode = 3 +) + +var gFromString = map[string]Mode{ // nolint: gochecknoglobals + "": Executable, + "link": Executable, + "create": Executable, + "default": Executable, + "executable": Executable, + "library": Library, + "shared": Library, + "archive": Archive, + "static": Archive, + "object": Object, + "compile": Object, +} + +var gToString = map[Mode]string{ // nolint: gochecknoglobals + Executable: "executable", + Library: "library", + Archive: "archive", + Object: "object", +} + +// Mode defines compiler mode like creating executable, library, archive or object. +type Mode int + +// String returns compiler mode as a string. +func (m Mode) String() string { + return gToString[m] +} + +// UnmarshalText decodes text to compiler mode. +func (m *Mode) UnmarshalText(data []byte) error { + if value, ok := gFromString[strings.TrimSpace(strings.ToLower(string(data)))]; ok { + *m = value + return nil + } + + return rterror.New("error occurred while decoding text to compiler mode", string(data)) +} + +// MarshalText encodes compiler mode to text. +func (m Mode) MarshalText() (data []byte, err error) { + return []byte(m.String()), nil +} diff --git a/mode/mode_test.go b/mode/mode_test.go new file mode 100644 index 0000000..7958f48 --- /dev/null +++ b/mode/mode_test.go @@ -0,0 +1,51 @@ +// Copyright 2020 Tymoteusz Blazejczyk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mode_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "gitlab.com/tymonx/xlogic-toolchain/mode" +) + +func TestModeString(test *testing.T) { + assert.Equal(test, "object", mode.Object.String()) + assert.Equal(test, "archive", mode.Archive.String()) + assert.Equal(test, "library", mode.Library.String()) + assert.Equal(test, "executable", mode.Executable.String()) +} + +func TestModeUnmarshalText(test *testing.T) { + var m mode.Mode + + assert.NoError(test, json.Unmarshal([]byte(` " object" `), &m)) + assert.Equal(test, mode.Object, m) +} + +func TestModeUnmarshalTextError(test *testing.T) { + var m mode.Mode + + assert.Error(test, json.Unmarshal([]byte(`"invalid"`), &m)) + assert.Equal(test, mode.Executable, m) +} + +func TestModeMarshalText(test *testing.T) { + data, err := json.Marshal(mode.Archive) + + assert.NoError(test, err) + assert.Equal(test, []byte(`"archive"`), data) +} diff --git a/option/option.go b/option/option.go deleted file mode 100644 index da3be19..0000000 --- a/option/option.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package option - -import ( - "flag" - - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/define" - "gitlab.com/tymonx/xlogic-toolchain/resource/header" - "gitlab.com/tymonx/xlogic-toolchain/resource/include" -) - -// Option defines compiler options. -type Option struct { - Compile bool - Append bool - Static bool - Shared bool - Help bool - Output path.Path - Defines define.Defines - Headers header.Headers - Includes include.Includes -} - -// New creates a new option object. -func New() *Option { - return &Option{} -} - -// FlagSet sets flags. -func (o *Option) FlagSet(f *flag.FlagSet) *Option { - f.BoolVar(&o.Help, - "help", - false, - "Print help", - ) - - f.StringVar((*string)(&o.Output), - "o", - "output.json", - "Place output in file", - ) - - f.Var(&o.Includes, - "I", - "Directory to search for includes", - ) - - f.Var(&o.Headers, - "include", - "Process file as if appeared as the first line of the primary source file", - ) - - f.Var(&o.Defines, - "D", - "Set preprocessor define as NAME or NAME=VALUE", - ) - - f.Var(&define.Undefines{Defines: &o.Defines}, - "U", - "Undefine preprocessor define NAME", - ) - - f.BoolVar(&o.Compile, - "c", - false, - "Compile or assemble the source files, but do not link", - ) - - f.BoolVar(&o.Append, - "append", - false, - "Add files to existing archive", - ) - - f.BoolVar(&o.Static, - "static", - false, - "Prevents linking with the shared libraries", - ) - - f.BoolVar(&o.Shared, - "shared", - false, - "Produce a shared object which can then be linked with other objects to form an executable", - ) - - return o -} diff --git a/resource/archive/acrhives.go b/resource/archive/acrhives.go deleted file mode 100644 index 7f75522..0000000 --- a/resource/archive/acrhives.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package archive - -// Archives defines a list of archive files with compiled source files. -type Archives []*Archive diff --git a/resource/archive/archive.go b/resource/archive/archive.go deleted file mode 100644 index dc76d7c..0000000 --- a/resource/archive/archive.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package archive - -import ( - "strings" - - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/object" -) - -var gExtension = map[string]bool{ // nolint: gochecknoglobals - ".a": true, - ".lib": true, -} - -// Archive defines storage to archive compiled object files. -type Archive struct { - Path path.Path `json:"path,omitempty"` - Object object.Objects `json:"object,omitempty"` -} - -// Is returns true if path is a archive file, otherwise it returns false. -func Is(file path.Path) bool { - return gExtension[strings.ToLower(file.Extension())] -} - -// New creates a new archive object. -func New(file path.Path) *Archive { - return &Archive{ - Path: file, - } -} diff --git a/resource/executable/executable.go b/resource/executable/executable.go deleted file mode 100644 index ac79b55..0000000 --- a/resource/executable/executable.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package executable - -import ( - "strings" - - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/archive" - "gitlab.com/tymonx/xlogic-toolchain/resource/define" - "gitlab.com/tymonx/xlogic-toolchain/resource/header" - "gitlab.com/tymonx/xlogic-toolchain/resource/include" - "gitlab.com/tymonx/xlogic-toolchain/resource/library" - "gitlab.com/tymonx/xlogic-toolchain/resource/object" - "gitlab.com/tymonx/xlogic-toolchain/resource/source" -) - -var gExtension = map[string]bool{ // nolint: gochecknoglobals - "": true, - ".exe": true, -} - -// Executable defines an executable. -type Executable struct { - Path path.Path `json:"path,omitempty"` - Object object.Objects `json:"object,omitempty"` - Source source.Sources `json:"source,omitempty"` - Define define.Defines `json:"define,omitempty"` - Header header.Headers `json:"header,omitempty"` - Include include.Includes `json:"include,omitempty"` - Archive archive.Archives `json:"archive,omitempty"` - Library library.Libraries `json:"library,omitempty"` -} - -// Is returns true if path is an executable, otherwise it returns false. -func Is(file path.Path) bool { - return gExtension[strings.ToLower(file.Extension())] -} - -// New creates a new executable object. -func New(file path.Path) *Executable { - return &Executable{ - Path: file, - } -} diff --git a/resource/kind/kind.go b/resource/kind/kind.go deleted file mode 100644 index c6b2eeb..0000000 --- a/resource/kind/kind.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kind - -import ( - "strings" -) - -// These constants define values for single resource. -const ( - Unknown Kind = 0 - Generic Kind = 1 - Source Kind = 2 - Header Kind = 3 - Define Kind = 4 - Output Kind = 5 - Object Kind = 6 - Include Kind = 7 - Archive Kind = 8 - Library Kind = 9 - Executable Kind = 10 -) - -var gToString = map[Kind]string{ // nolint: gochecknoglobals - Unknown: "", - Generic: "generic", - Source: "source", - Header: "header", - Define: "define", - Output: "output", - Object: "object", - Include: "include", - Archive: "archive", - Library: "library", - Executable: "executable", -} - -var gFromString = map[string]Kind{ // nolint: gochecknoglobals - "": Unknown, - "generic": Generic, - "source": Source, - "header": Header, - "define": Define, - "output": Output, - "object": Object, - "include": Include, - "archive": Archive, - "library": Library, - "executable": Executable, -} - -// Kind defines resource kind. -type Kind int - -// New returns a new kind from given string. -func New(str string) Kind { - return gFromString[strings.TrimSpace(strings.ToLower(str))] -} - -// String returns kind as string. -func (k *Kind) String() string { - return gToString[*k] -} - -// UnmarshalJSON decodes from JSON to kind. -func (k *Kind) UnmarshalJSON(data []byte) error { - *k = New(strings.Trim(string(data), `"`)) - - return nil -} - -// MarshalJSON decodes from kind to JSON. -func (k *Kind) MarshalJSON() (data []byte, err error) { - return []byte(`"` + k.String() + `"`), nil -} diff --git a/resource/kind/kind_test.go b/resource/kind/kind_test.go deleted file mode 100644 index cbe10d6..0000000 --- a/resource/kind/kind_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kind_test - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - - "gitlab.com/tymonx/xlogic-toolchain/resource/kind" -) - -func TestKindFromString(test *testing.T) { - assert.Equal(test, kind.Archive, kind.New(" archiVe ")) - assert.Equal(test, kind.Define, kind.New(" define")) - assert.Equal(test, kind.Executable, kind.New("executable")) - assert.Equal(test, kind.Header, kind.New("Header")) - assert.Equal(test, kind.Library, kind.New(" library ")) -} - -func TestKindString(test *testing.T) { - k := kind.New(" ArchiVe") - - assert.Equal(test, "archive", k.String()) -} - -func TestKindUnmarshalJSON(test *testing.T) { - var k kind.Kind - - assert.NoError(test, json.Unmarshal([]byte(` " object " `), &k)) - assert.Equal(test, kind.Object, k) -} - -func TestKindMarshalJSON(test *testing.T) { - k := kind.New("SouRCE") - - data, err := json.Marshal(&k) - - assert.NoError(test, err) - assert.Equal(test, []byte(`"source"`), data) -} diff --git a/resource/library/libraries.go b/resource/library/libraries.go deleted file mode 100644 index 5137337..0000000 --- a/resource/library/libraries.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package library - -// Libraries returns a list of shared libraries. -type Libraries []*Library diff --git a/resource/library/library.go b/resource/library/library.go deleted file mode 100644 index 7e0ccbf..0000000 --- a/resource/library/library.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package library - -import ( - "strings" - - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/archive" - "gitlab.com/tymonx/xlogic-toolchain/resource/define" - "gitlab.com/tymonx/xlogic-toolchain/resource/header" - "gitlab.com/tymonx/xlogic-toolchain/resource/include" - "gitlab.com/tymonx/xlogic-toolchain/resource/object" - "gitlab.com/tymonx/xlogic-toolchain/resource/source" -) - -var gExtension = map[string]bool{ // nolint: gochecknoglobals - ".so": true, - ".dll": true, -} - -// Library defines a shared library. -type Library struct { - Path path.Path `json:"path,omitempty"` - Object object.Objects `json:"object,omitempty"` - Source source.Sources `json:"source,omitempty"` - Define define.Defines `json:"define,omitempty"` - Header header.Headers `json:"header,omitempty"` - Include include.Includes `json:"include,omitempty"` - Archive archive.Archives `json:"archive,omitempty"` -} - -// Is returns true if path is a library file, otherwise it returns false. -func Is(file path.Path) bool { - return gExtension[strings.ToLower(file.Extension())] -} - -// New creates a new library object. -func New(file path.Path) *Library { - return &Library{ - Path: file, - } -} diff --git a/resource/object/object.go b/resource/object/object.go deleted file mode 100644 index 41ec541..0000000 --- a/resource/object/object.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package object - -import ( - "strings" - - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/define" - "gitlab.com/tymonx/xlogic-toolchain/resource/header" - "gitlab.com/tymonx/xlogic-toolchain/resource/include" - "gitlab.com/tymonx/xlogic-toolchain/resource/source" -) - -var gExtension = map[string]bool{ // nolint: gochecknoglobals - ".o": true, - ".obj": true, -} - -// Object defines compiled source file or files to object. -type Object struct { - Path path.Path `json:"path,omitempty"` - Sources source.Sources `json:"source,omitempty"` - Defines define.Defines `json:"define,omitempty"` - Headers header.Headers `json:"header,omitempty"` - Includes include.Includes `json:"include,omitempty"` -} - -// Is returns true if path is a archive file, otherwise it returns false. -func Is(file path.Path) bool { - return gExtension[strings.ToLower(file.Extension())] -} - -// New creates a new object. -func New(file path.Path) *Object { - return &Object{ - Path: file, - } -} diff --git a/resource/object/objects.go b/resource/object/objects.go deleted file mode 100644 index b997e3d..0000000 --- a/resource/object/objects.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package object - -// Objects defines a list of compiled object files. -type Objects []*Object diff --git a/resource/output/kind/kind.go b/resource/output/kind/kind.go deleted file mode 100644 index 2556f44..0000000 --- a/resource/output/kind/kind.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kind - -import ( - "strings" - - "gitlab.com/tymonx/xlogic-toolchain/path" -) - -// These constants define values for generted output file. -const ( - Unknown Kind = 0 - File Kind = 1 - Text Kind = 2 - Binary Kind = 3 - Object Kind = 4 - Source Kind = 5 - Header Kind = 6 - Script Kind = 7 - Executable Kind = 8 -) - -var gToString = map[Kind]string{ // nolint: gochecknoglobals - Unknown: "", - File: "file", - Text: "text", - Binary: "binary", - Object: "object", - Source: "source", - Header: "header", - Script: "script", - Executable: "executable", -} - -var gFromString = map[string]Kind{ // nolint: gochecknoglobals - "": Unknown, - "file": File, - "text": Text, - "binary": Binary, - "object": Object, - "source": Source, - "header": Header, - "script": Script, - "executable": Executable, -} - -var gFromExtension = map[string]Kind{ // nolint: gochecknoglobals - ".txt": Text, - ".o": Object, - ".exe": Executable, -} - -// Kind defines generated output file kind. -type Kind int - -// FromString returns kind from given string. -func FromString(str string) Kind { - return gFromString[strings.TrimSpace(strings.ToLower(str))] -} - -// FromPath returns kind from given file path. -func FromPath(file path.Path) Kind { - return gFromExtension[strings.ToLower(file.Extension())] -} - -// String returns kind as string. -func (k *Kind) String() string { - return gToString[*k] -} - -// UnmarshalJSON decodes from JSON to kind. -func (k *Kind) UnmarshalJSON(data []byte) error { - *k = FromString(strings.Trim(string(data), `"`)) - - return nil -} - -// MarshalJSON decodes from kind to JSON. -func (k *Kind) MarshalJSON() (data []byte, err error) { - return []byte(`"` + k.String() + `"`), nil -} diff --git a/resource/output/kind/kind_test.go b/resource/output/kind/kind_test.go deleted file mode 100644 index 7d8e260..0000000 --- a/resource/output/kind/kind_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kind_test - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - - "gitlab.com/tymonx/xlogic-toolchain/resource/output/kind" -) - -func TestKindFromString(test *testing.T) { - assert.Equal(test, kind.File, kind.FromString(" file")) - assert.Equal(test, kind.Text, kind.FromString("teXt")) - assert.Equal(test, kind.Binary, kind.FromString(" BinaRY")) - assert.Equal(test, kind.Executable, kind.FromString(" executable")) -} - -func TestKindFromPath(test *testing.T) { - assert.Equal(test, kind.Text, kind.FromPath("dir/file.txt")) - assert.Equal(test, kind.Executable, kind.FromPath("dir/file.exe")) -} - -func TestKindString(test *testing.T) { - k := kind.FromPath("dir/file.o") - - assert.Equal(test, "object", k.String()) -} - -func TestKindUnmarshalJSON(test *testing.T) { - var k kind.Kind - - assert.NoError(test, json.Unmarshal([]byte(` " Script " `), &k)) - assert.Equal(test, kind.Script, k) -} - -func TestKindMarshalJSON(test *testing.T) { - k := kind.FromPath("dir/file.o") - - data, err := json.Marshal(&k) - - assert.NoError(test, err) - assert.Equal(test, []byte(`"object"`), data) -} diff --git a/resource/output/metadata/metadata.go b/resource/output/metadata/metadata.go deleted file mode 100644 index 19c55bd..0000000 --- a/resource/output/metadata/metadata.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package metadata - -// Metadata defines metadata for generated output file. -type Metadata map[string]interface{} diff --git a/resource/output/output.go b/resource/output/output.go deleted file mode 100644 index 7f231cd..0000000 --- a/resource/output/output.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package output - -import ( - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/output/kind" - "gitlab.com/tymonx/xlogic-toolchain/resource/output/metadata" -) - -// Output defines single generated output file. -type Output struct { - Kind kind.Kind `json:"kind,omitempty"` - Path path.Path `json:"path,omitempty"` - Metadata metadata.Metadata `json:"metadata,omitempty"` -} - -// New creates a new generated output file object from given file path. -func New(file path.Path) *Output { - return &Output{ - Kind: kind.FromPath(file), - Path: file, - } -} diff --git a/resource/output/outputs.go b/resource/output/outputs.go deleted file mode 100644 index 2bbcf07..0000000 --- a/resource/output/outputs.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package output - -// Outputs defines a list of generated output files. -type Outputs []*Output diff --git a/resource/resource.go b/resource/resource.go deleted file mode 100644 index 7d460ae..0000000 --- a/resource/resource.go +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package resource - -import ( - "encoding/json" - "strings" - - "gitlab.com/tymonx/xlogic-toolchain/cerr" - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/archive" - "gitlab.com/tymonx/xlogic-toolchain/resource/define" - "gitlab.com/tymonx/xlogic-toolchain/resource/executable" - "gitlab.com/tymonx/xlogic-toolchain/resource/header" - "gitlab.com/tymonx/xlogic-toolchain/resource/id" - "gitlab.com/tymonx/xlogic-toolchain/resource/include" - "gitlab.com/tymonx/xlogic-toolchain/resource/kind" - "gitlab.com/tymonx/xlogic-toolchain/resource/library" - "gitlab.com/tymonx/xlogic-toolchain/resource/object" - "gitlab.com/tymonx/xlogic-toolchain/resource/output" - "gitlab.com/tymonx/xlogic-toolchain/resource/source" -) - -var gExtension = map[string]bool{ // nolint: gochecknoglobals - ".json": true, -} - -// Resource defines a single resource. JSON API compatibility. -type Resource struct { - Kind kind.Kind `json:"type"` - ID id.ID `json:"id"` - Attributes interface{} `json:"attributes,omitempty"` -} - -// Is returns true if path is a resource file, otherwise it returns false. -func Is(file path.Path) bool { - return gExtension[strings.ToLower(file.Extension())] -} - -// New creates a new resource. -func New(k kind.Kind) *Resource { - return &Resource{ - ID: id.New(), - Kind: k, - Attributes: create(k), - } -} - -func newWith(k kind.Kind, attributes interface{}) *Resource { - return &Resource{ - ID: id.New(), - Kind: k, - Attributes: attributes, - } -} - -// Load loads resource from file. -func Load(file path.Path) (r *Resource, err error) { - if Is(file) { - r = new(Resource) - - if err := r.Load(file); err != nil { - return nil, err - } - - return r, nil - } - - if library.Is(file) { - return newWith(kind.Library, library.New(file)), nil - } - - if archive.Is(file) { - return newWith(kind.Archive, archive.New(file)), nil - } - - if object.Is(file) { - return newWith(kind.Object, object.New(file)), nil - } - - if source.Is(file) { - return newWith(kind.Source, source.New(file)), nil - } - - if header.Is(file) { - return newWith(kind.Header, header.New(file)), nil - } - - if include.Is(file) { - return newWith(kind.Include, include.New(file)), nil - } - - r = new(Resource) - - if err := r.Load(file); err != nil { - return nil, err - } - - return r, nil -} - -// Loads loads resources from given files. -func Loads(files path.Paths) (r Resources, err error) { - r = make(Resources, len(files)) - - for i, file := range files { - if r[i], err = Load(file); err != nil { - return nil, err - } - } - - return r, nil -} - -// Generic returns generic resource. -func (r *Resource) Generic() map[string]interface{} { - return r.Attributes.(map[string]interface{}) -} - -// Archive returns archive resource. -func (r *Resource) Archive() *archive.Archive { - return r.Attributes.(*archive.Archive) -} - -// Library returns library resource. -func (r *Resource) Library() *library.Library { - return r.Attributes.(*library.Library) -} - -// Define returns define resource. -func (r *Resource) Define() *define.Define { - return r.Attributes.(*define.Define) -} - -// Header returns header resource. -func (r *Resource) Header() *header.Header { - return r.Attributes.(*header.Header) -} - -// Include returns include resource. -func (r *Resource) Include() *include.Include { - return r.Attributes.(*include.Include) -} - -// Object returns object resource. -func (r *Resource) Object() *object.Object { - return r.Attributes.(*object.Object) -} - -// Output returns output resource. -func (r *Resource) Output() *output.Output { - return r.Attributes.(*output.Output) -} - -// Source returns source resource. -func (r *Resource) Source() *source.Source { - return r.Attributes.(*source.Source) -} - -// Executable returns executable resource. -func (r *Resource) Executable() *executable.Executable { - return r.Attributes.(*executable.Executable) -} - -// Load loads from file. -func (r *Resource) Load(file path.Path) error { - return file.Load(r) -} - -// Dump dumps to file. -func (r *Resource) Dump(file path.Path) error { - return file.Dump(r) -} - -// UnmarshalJSON decodes JSON to resource. -func (r *Resource) UnmarshalJSON(data []byte) error { - if data[0] != '{' { - return cerr.InvalidValue - } - - obj := &struct { - ID id.ID `json:"id"` - Kind kind.Kind `json:"type"` - }{} - - if err := json.Unmarshal(data, obj); err != nil { - return err - } - - attrs := &struct { - Attributes interface{} `json:"attributes"` - }{ - Attributes: create(obj.Kind), - } - - if err := json.Unmarshal(data, attrs); err != nil { - return err - } - - r.ID = obj.ID - r.Kind = obj.Kind - r.Attributes = attrs.Attributes - - return nil -} - -func create(k kind.Kind) interface{} { - switch k { - case kind.Source: - return new(source.Source) - case kind.Object: - return new(object.Object) - case kind.Archive: - return new(archive.Archive) - case kind.Library: - return new(library.Library) - case kind.Include: - return new(include.Include) - case kind.Define: - return new(define.Define) - case kind.Header: - return new(header.Header) - case kind.Output: - return new(output.Output) - case kind.Executable: - return new(executable.Executable) - default: - return make(map[string]interface{}) - } -} diff --git a/resource/resources.go b/resource/resources.go deleted file mode 100644 index df64e03..0000000 --- a/resource/resources.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package resource - -// Resources defines a list of resources. JSON API compatibility. -type Resources []*Resource diff --git a/resource/source/kind/kind.go b/resource/source/kind/kind.go deleted file mode 100644 index d7ba90e..0000000 --- a/resource/source/kind/kind.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kind - -import ( - "strings" - - "gitlab.com/tymonx/xlogic-toolchain/path" -) - -// These constants define values for source file. -const ( - Unknown Kind = 0 - C Kind = 1 - IP Kind = 2 - Cxx Kind = 3 - TCL Kind = 4 - JSON Kind = 5 - VHDL Kind = 6 - Verilog Kind = 7 - SystemVerilog Kind = 8 -) - -var gToString = map[Kind]string{ // nolint: gochecknoglobals - Unknown: "", - C: "c", - IP: "ip", - Cxx: "c++", - TCL: "tcl", - JSON: "json", - VHDL: "vhdl", - Verilog: "verilog", - SystemVerilog: "systemverilog", -} - -var gFromString = map[string]Kind{ // nolint: gochecknoglobals - "": Unknown, - "c": C, - "ip": IP, - "c++": Cxx, - "tcl": TCL, - "json": JSON, - "vhdl": VHDL, - "verilog": Verilog, - "sv": SystemVerilog, - "systemverilog": SystemVerilog, -} - -var gFromExtension = map[string]Kind{ // nolint: gochecknoglobals - ".c": C, - ".ip": IP, - ".cc": Cxx, - ".cxx": Cxx, - ".cpp": Cxx, - ".c++": Cxx, - ".tcl": TCL, - ".vhd": VHDL, - ".vhdl": VHDL, - ".json": JSON, - ".v": Verilog, - ".sv": SystemVerilog, -} - -// Kind defines source file kind. -type Kind int - -// Is returns true if path is a source file, otherwise it returns false. -func Is(file path.Path) bool { - return gFromExtension[strings.ToLower(file.Extension())] != Unknown -} - -// FromString returns kind from given string. -func FromString(str string) Kind { - return gFromString[strings.TrimSpace(strings.ToLower(str))] -} - -// FromPath returns kind from given file path. -func FromPath(file path.Path) Kind { - return gFromExtension[strings.ToLower(file.Extension())] -} - -// String returns kind as string. -func (k *Kind) String() string { - return gToString[*k] -} - -// UnmarshalText decodes from text to kind. -func (k *Kind) UnmarshalText(data []byte) error { - *k = FromString(string(data)) - return nil -} - -// MarshalText decodes from kind to text. -func (k *Kind) MarshalText() (data []byte, err error) { - return []byte(k.String()), nil -} diff --git a/resource/source/kind/kind_test.go b/resource/source/kind/kind_test.go deleted file mode 100644 index cc88e16..0000000 --- a/resource/source/kind/kind_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kind_test - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - - "gitlab.com/tymonx/xlogic-toolchain/resource/source/kind" -) - -func TestKindFromString(test *testing.T) { - assert.Equal(test, kind.C, kind.FromString("c ")) - assert.Equal(test, kind.IP, kind.FromString("IP")) - assert.Equal(test, kind.Cxx, kind.FromString("C++")) - assert.Equal(test, kind.TCL, kind.FromString("tCL")) - assert.Equal(test, kind.VHDL, kind.FromString("Vhdl ")) - assert.Equal(test, kind.Verilog, kind.FromString(" VeRILOG")) - assert.Equal(test, kind.SystemVerilog, kind.FromString(" SystemVERILOG ")) -} - -func TestKindFromPath(test *testing.T) { - assert.Equal(test, kind.C, kind.FromPath("dir/file.c")) - assert.Equal(test, kind.IP, kind.FromPath("dir/file.ip")) - assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.cc")) - assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.cpp")) - assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.cxx")) - assert.Equal(test, kind.Cxx, kind.FromPath("dir/file.c++")) - assert.Equal(test, kind.TCL, kind.FromPath("dir/file.tcl")) - assert.Equal(test, kind.VHDL, kind.FromPath("dir/file.Vhdl")) - assert.Equal(test, kind.Verilog, kind.FromPath("dir/file.V")) - assert.Equal(test, kind.SystemVerilog, kind.FromPath("dir/file.sV")) -} - -func TestKindIs(test *testing.T) { - assert.True(test, kind.Is("dir/file.vhd")) - assert.False(test, kind.Is("dir/dir2")) -} - -func TestKindString(test *testing.T) { - k := kind.FromPath("dir/file.sv") - - assert.Equal(test, "systemverilog", k.String()) -} - -func TestKindUnmarshalJSON(test *testing.T) { - var k kind.Kind - - assert.NoError(test, json.Unmarshal([]byte(` " SystemVerilOg " `), &k)) - assert.Equal(test, kind.SystemVerilog, k) -} - -func TestKindMarshalJSON(test *testing.T) { - k := kind.FromPath("dir/file.v") - - data, err := json.Marshal(&k) - - assert.NoError(test, err) - assert.Equal(test, []byte(`"verilog"`), data) -} diff --git a/resource/source/source.go b/resource/source/source.go deleted file mode 100644 index 6b2c5d0..0000000 --- a/resource/source/source.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package source - -import ( - "encoding/json" - - "gitlab.com/tymonx/go-error/rterror" - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/source/kind" -) - -// Source defines single source file. -type Source struct { - Kind kind.Kind `json:"kind,omitempty"` - Path path.Path `json:"path,omitempty"` -} - -// New creates a new source object. -func New(file path.Path) *Source { - return &Source{ - Kind: kind.FromPath(file), - Path: file, - } -} - -// Is returns true if path is a source file, otherwise it returns false. -func Is(file path.Path) bool { - return kind.Is(file) -} - -// String returns path string. -func (s *Source) String() string { - return s.Path.String() -} - -// UnmarshalText decodes text to source file path. -func (s *Source) UnmarshalText(data []byte) error { - s.Path = path.Path(data) - s.Kind = kind.FromPath(s.Path) - - return nil -} - -// UnmarshalJSON decodes JSON to source file path. -func (s *Source) UnmarshalJSON(data []byte) error { - switch data[0] { - case '{': - case '"': - return s.UnmarshalText(data[1 : len(data)-1]) - case 'n': - *s = Source{} - return nil - default: - return rterror.New("invalid JSON type") - } - - object := new(struct { - Kind kind.Kind `json:"kind"` - Path path.Path `json:"path"` - }) - - if err := json.Unmarshal(data, object); err != nil { - return rterror.New("error occurred while decoding JSON", err) - } - - s.Kind = object.Kind - s.Path = object.Path - - if s.Kind == kind.Unknown { - s.Kind = kind.FromPath(s.Path) - } - - return nil -} diff --git a/resource/source/source_test.go b/resource/source/source_test.go deleted file mode 100644 index a599b95..0000000 --- a/resource/source/source_test.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package source_test - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/path" - "gitlab.com/tymonx/xlogic-toolchain/resource/source" - "gitlab.com/tymonx/xlogic-toolchain/resource/source/kind" -) - -func TestSourceNew(test *testing.T) { - want := "file.c" - - s := source.New(path.Path(want)) - - assert.NotNil(test, s) - assert.Equal(test, kind.C, s.Kind) - assert.Equal(test, "c", s.Kind.String()) - assert.Equal(test, want, s.Path.String()) -} - -func TestSourceString(test *testing.T) { - want := "file.sv" - - assert.NotNil(test, want, source.New(path.Path(want)).String()) -} - -func TestSourceIs(test *testing.T) { - assert.True(test, source.Is("dir/file.c++")) - assert.False(test, source.Is("/dir/dir")) -} - -func TestSourceUnmarshalText(test *testing.T) { - want := "dir/file.sv" - - s := new(source.Source) - - assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), s)) - - assert.Equal(test, want, s.Path.String()) - assert.Equal(test, kind.SystemVerilog, s.Kind) - assert.Equal(test, "systemverilog", s.Kind.String()) -} - -func TestSourceUnmarshalJSONObject(test *testing.T) { - want := "dir/file.tcl" - - s := new(source.Source) - - assert.NoError(test, json.Unmarshal([]byte(` { "path": "`+want+`" } `), s)) - - assert.Equal(test, want, s.Path.String()) - assert.Equal(test, kind.TCL, s.Kind) - assert.Equal(test, "tcl", s.Kind.String()) -} - -func TestSourceUnmarshalJSONNull(test *testing.T) { - s := new(source.Source) - - assert.NoError(test, json.Unmarshal([]byte(` null `), s)) - - assert.Empty(test, s.Path.String()) - assert.Empty(test, s.Kind.String()) - assert.Equal(test, kind.Unknown, s.Kind) -} - -func TestSourceUnmarshalJSONError(test *testing.T) { - s := new(source.Source) - - assert.Error(test, json.Unmarshal([]byte(`{"path":5}`), s)) - - assert.Empty(test, s.Path.String()) - assert.Empty(test, s.Kind.String()) - assert.Equal(test, kind.Unknown, s.Kind) -} - -func TestSourceUnmarshalJSONInvalid(test *testing.T) { - s := new(source.Source) - - assert.Error(test, json.Unmarshal([]byte(`true`), s)) - - assert.Empty(test, s.Path.String()) - assert.Empty(test, s.Kind.String()) - assert.Equal(test, kind.Unknown, s.Kind) -} diff --git a/resource/source/sources.go b/resource/source/sources.go deleted file mode 100644 index 8a63561..0000000 --- a/resource/source/sources.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package source - -import ( - "encoding/json" - - "gitlab.com/tymonx/go-error/rterror" - "gitlab.com/tymonx/xlogic-toolchain/path" -) - -// Sources defines a list of source files. -type Sources []*Source - -// UnmarshalText decodes text to source file path. -func (s *Sources) UnmarshalText(data []byte) error { - *s = Sources{New(path.Path(data))} - - return nil -} - -// UnmarshalJSON decodes JSON to source file path. -func (s *Sources) UnmarshalJSON(data []byte) error { - switch data[0] { - case '[': - case '{': - object := new(Source) - - if err := json.Unmarshal(data, object); err != nil { - return err - } - - *s = Sources{object} - - return nil - case '"': - return s.UnmarshalText(data[1 : len(data)-1]) - case 'n': - *s = Sources{} - return nil - default: - return rterror.New("invalid JSON type") - } - - sources := []*Source{} - - if err := json.Unmarshal(data, &sources); err != nil { - return rterror.New("error occurred while decoding JSON", err) - } - - *s = sources - - return nil -} diff --git a/resource/source/sources_test.go b/resource/source/sources_test.go deleted file mode 100644 index 7e4ae4a..0000000 --- a/resource/source/sources_test.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2020 Tymoteusz Blazejczyk -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package source_test - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/source" - "gitlab.com/tymonx/xlogic-toolchain/resource/source/kind" -) - -func TestSourcesUnmarshalText(test *testing.T) { - want := "dir/file.c++" - - var s source.Sources - - assert.NoError(test, json.Unmarshal([]byte(` "`+want+`" `), &s)) - - assert.Len(test, s, 1) - assert.Equal(test, kind.Cxx, s[0].Kind) - assert.Equal(test, "c++", s[0].Kind.String()) - assert.Equal(test, want, s[0].Path.String()) -} - -func TestSourcesUnmarshalJSON(test *testing.T) { - var s source.Sources - - assert.NoError(test, json.Unmarshal([]byte(` ["dir/file.c", { "path": "file.tcl" }]`), &s)) - - assert.Len(test, s, 2) - - assert.Equal(test, kind.C, s[0].Kind) - assert.Equal(test, "c", s[0].Kind.String()) - assert.Equal(test, "dir/file.c", s[0].Path.String()) - - assert.Equal(test, kind.TCL, s[1].Kind) - assert.Equal(test, "tcl", s[1].Kind.String()) - assert.Equal(test, "file.tcl", s[1].Path.String()) -} - -func TestSourcesUnmarshalJSONObject(test *testing.T) { - want := "dir/file.json" - - var s source.Sources - - assert.NoError(test, json.Unmarshal([]byte(` { "path": "`+want+`" } `), &s)) - - assert.Len(test, s, 1) - assert.Equal(test, want, s[0].Path.String()) - assert.Equal(test, kind.JSON, s[0].Kind) - assert.Equal(test, "json", s[0].Kind.String()) -} - -func TestSourcesUnmarshalJSONNull(test *testing.T) { - var s source.Sources - - assert.NoError(test, json.Unmarshal([]byte(` null `), &s)) - assert.Empty(test, s) -} - -func TestSourcesUnmarshalJSONError(test *testing.T) { - var s source.Sources - - assert.Error(test, json.Unmarshal([]byte(`[5]`), &s)) - assert.Empty(test, s) -} - -func TestSourcesUnmarshalJSONObjectError(test *testing.T) { - var s source.Sources - - assert.Error(test, json.Unmarshal([]byte(`{"path":5}`), &s)) - assert.Empty(test, s) -} - -func TestSourcesUnmarshalJSONInvalid(test *testing.T) { - var s source.Sources - - assert.Error(test, json.Unmarshal([]byte(`true`), &s)) - assert.Empty(test, s) -} diff --git a/resource/undefine/undefine.go b/undefine/undefine.go similarity index 100% rename from resource/undefine/undefine.go rename to undefine/undefine.go diff --git a/resource/undefine/undefine_test.go b/undefine/undefine_test.go similarity index 97% rename from resource/undefine/undefine_test.go rename to undefine/undefine_test.go index 6217d5d..867a026 100644 --- a/resource/undefine/undefine_test.go +++ b/undefine/undefine_test.go @@ -19,7 +19,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/undefine" + "gitlab.com/tymonx/xlogic-toolchain/undefine" ) func TestUndefineNew(test *testing.T) { diff --git a/resource/undefine/undefines.go b/undefine/undefines.go similarity index 92% rename from resource/undefine/undefines.go rename to undefine/undefines.go index e3651c9..cca7c44 100644 --- a/resource/undefine/undefines.go +++ b/undefine/undefines.go @@ -21,11 +21,11 @@ import ( ) // Undefines undefines a list of undefines. -type Undefines []*Undefine +type Undefines []Undefine // UnmarshalText decodes text to undefine. func (u *Undefines) UnmarshalText(data []byte) error { - *u = Undefines{New(string(data))} + *u = Undefines{*New(string(data))} return nil } @@ -41,7 +41,7 @@ func (u *Undefines) UnmarshalJSON(data []byte) error { return err } - *u = Undefines{object} + *u = Undefines{*object} return nil case '"': @@ -53,7 +53,7 @@ func (u *Undefines) UnmarshalJSON(data []byte) error { return rterror.New("invalid JSON type") } - undefines := []*Undefine{} + undefines := []Undefine{} if err := json.Unmarshal(data, &undefines); err != nil { return rterror.New("error occurred while decoding JSON", err) diff --git a/resource/undefine/undefines_test.go b/undefine/undefines_test.go similarity index 97% rename from resource/undefine/undefines_test.go rename to undefine/undefines_test.go index 4b3756d..df24e59 100644 --- a/resource/undefine/undefines_test.go +++ b/undefine/undefines_test.go @@ -19,7 +19,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "gitlab.com/tymonx/xlogic-toolchain/resource/undefine" + "gitlab.com/tymonx/xlogic-toolchain/undefine" ) func TestUndefinesUnmarshalText(test *testing.T) { -- GitLab From 76e7f526e2db96175ef26eaf2c6dc0569eca8288 Mon Sep 17 00:00:00 2001 From: Tymoteusz Blazejczyk Date: Sun, 1 Nov 2020 17:50:44 +0100 Subject: [PATCH 12/12] Workaround for interfacer --- file/file.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/file/file.go b/file/file.go index 15b5674..5e0d990 100644 --- a/file/file.go +++ b/file/file.go @@ -77,14 +77,13 @@ func (f *File) Load(p path.Path) (err error) { // Dump dumps file content. func (f *File) Dump(p path.Path) (err error) { - // use as a fmt.Stringer var data []byte if data, err = Marshal(f); err != nil { return rterror.New("cannot encode file to JSON", err) } - if err := ioutil.WriteFile(p.String(), data, 0600); err != nil { + if err := ioutil.WriteFile(string(p), data, 0600); err != nil { return rterror.New("cannot write to file", p, err) } -- GitLab