Skip to content

Commit

Permalink
Merge pull request #5 from ystia/feature/add_description-to-documenta…
Browse files Browse the repository at this point in the history
…tion

Add datatypes descriptions to generated comments
  • Loading branch information
loicalbertin committed Nov 15, 2019
2 parents f5eb5c9 + 23503a6 commit 7a18d2d
Show file tree
Hide file tree
Showing 16 changed files with 178 additions and 41 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ jobs:
HOME: /tmp/buildhome
- name: SonarCloud Scan
uses: sonarsource/sonarcloud-github-action@v1.1
# Do this only on push commit do not need to be re-analyzed on PR
if: github.event_name == 'push'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,18 @@ The goal of tdt2go is to create a generator that takes Data Types defined in a [

## Installation

### Install using go get

tdt2go can be installed using `go get`

```bash
go get -u https://github.com/ystia/tdt2go/cmd/tdt2go
```

## Binaries distributions

Binaries distributions could be downloaded from [github](https://github.com/ystia/tdt2go/releases)

## Command options

```bash
Expand Down Expand Up @@ -51,7 +57,7 @@ Flags:
- [x] Generation of TOSCA builtin types such as `version`, `range`, `scalar-unit`s ...
- [x] include/exclude filters
- [x] Type name mapping like `tosca\.datatypes\.(.+)` :arrow_right: `Normative${1}` so `tosca.datatypes.Credential` become `NormativeCredential`
- [ ] Use type or property description on generated comments
- [x] Use type or property description on generated comments
- [ ] Make use of TOSCA `constraints` and `default`
## Example
Expand Down
8 changes: 8 additions & 0 deletions internal/pkg/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"go/format"
"strings"
"text/template"

"github.com/ystia/tdt2go/internal/pkg/model"
Expand All @@ -16,6 +17,9 @@ type Generator struct {
// GenerateFile generates a formatted Go source file based on the given model.File representation
func (*Generator) GenerateFile(f model.File) ([]byte, error) {
t := template.New("generator")
t.Funcs(template.FuncMap{
"asComment": asComment,
})
t = template.Must(t.Parse(fileTemplate))

b := &bytes.Buffer{}
Expand All @@ -31,3 +35,7 @@ func (*Generator) GenerateFile(f model.File) ([]byte, error) {

return result, nil
}

func asComment(input string) string {
return strings.ReplaceAll(input, "\n", "\n// ")
}
25 changes: 25 additions & 0 deletions internal/pkg/generator/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,31 @@ func TestGenerator_GenerateFile(t *testing.T) {
},
},
}, false},
{"WithDescriptions", &Generator{}, args{
model.File{
Package: "simple",
DataTypes: []model.DataType{
{
Name: "MyDT",
FQDTN: "org.ystia.datatypes.MyDT",
Description: "A oneliner description",
Fields: []model.Field{
{Name: "F1", Type: "string"},
{Name: "F2", Type: "int", Description: "A multiline\ndescription"},
},
},
{
Name: "MyDerivedDT",
FQDTN: "org.ystia.datatypes.MyDerivedDT",
DerivedFrom: "MyDT",
Description: "A multiline\ndescription",
Fields: []model.Field{
{Name: "F3", Type: "[]string", Description: "A oneliner description"},
},
},
},
},
}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
7 changes: 5 additions & 2 deletions internal/pkg/generator/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ import (
){{ end }}
{{- range .DataTypes}}
// {{.Name}} is the generated representation of {{.FQDTN}} data type
// {{.Name}} is the generated representation of {{.FQDTN}} data type{{ if .Description }}
//
// {{ asComment .Description }}{{end}}
type {{.Name}} {{ if and (ne .DerivedFrom "") (eq (len .Fields) 0) }}{{.DerivedFrom}}{{ else }}struct {
{{- if ne .DerivedFrom ""}}
{{.DerivedFrom}}
{{- end}}
{{- range .Fields}}
{{- range .Fields}}{{ if .Description }}
// {{ asComment .Description }}{{end}}
{{.Name}} {{.Type}} {{- if ne .OriginalName ""}} {{ $tick }}mapstructure:"{{.OriginalName}}" json:"{{.OriginalName}},omitempty"{{ $tick }}{{end}}{{end}}
}
{{end}}{{end -}}
Expand Down
24 changes: 24 additions & 0 deletions internal/pkg/generator/testdata/golden/WithDescriptions
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Code generated by tdt2go
// DO NOT EDIT! ANY CHANGES MAY BE OVERWRITTEN.

package simple

// MyDT is the generated representation of org.ystia.datatypes.MyDT data type
//
// A oneliner description
type MyDT struct {
F1 string
// A multiline
// description
F2 int
}

// MyDerivedDT is the generated representation of org.ystia.datatypes.MyDerivedDT data type
//
// A multiline
// description
type MyDerivedDT struct {
MyDT
// A oneliner description
F3 []string
}
4 changes: 4 additions & 0 deletions internal/pkg/model/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ type DataType struct {
FQDTN string
// DerivedFrom is the parent Go struct identifier name
DerivedFrom string
// Description is the data type description field
Description string
// Fields are DataType fields (aka properties in TOSCA)
Fields []Field
}
Expand All @@ -30,4 +32,6 @@ type Field struct {
OriginalName string
// Type is the Go struct field type
Type string
// Description is the property description field
Description string
}
2 changes: 2 additions & 0 deletions internal/pkg/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func (p *Parser) ParseTypes(filePath string) ([]model.DataType, error) {
FQDTN: dtName,
DerivedFrom: p.convertTOSCAType(dt.DerivedFrom),
Fields: p.convertDTFields(dt.Properties),
Description: strings.Trim(dt.Description, " \t\n"),
})
}
sort.Sort(ts)
Expand All @@ -118,6 +119,7 @@ func (p *Parser) convertDTFields(props map[string]tosca.PropertyDefinition) []mo
Name: convertToGoIdentifier(pName),
OriginalName: pName,
Type: p.convertDTPropType(prop),
Description: strings.Trim(prop.Description, " \t\n"),
}
fields = append(fields, f)
}
Expand Down
46 changes: 34 additions & 12 deletions internal/pkg/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,38 +28,45 @@ func TestParser_ParseTypes(t *testing.T) {
Name: "Credential",
FQDTN: "tosca.datatypes.Credential",
DerivedFrom: "Root",
Description: "The Credential type is a complex TOSCA data Type used when describing authorization credentials\nused to access network accessible resources.",
Fields: []model.Field{
{
Name: "Keys",
OriginalName: "keys",
Type: "map[string]string",
Description: "The optional list of protocol-specific keys or assertions.",
},
{
Name: "Protocol",
OriginalName: "protocol",
Type: "string",
Description: "The optional protocol name.",
},
{
Name: "Token",
OriginalName: "token",
Type: "string",
Description: "The required token used as a credential\nfor authorization or access to a networked resource.",
},
{
Name: "TokenType",
OriginalName: "token_type",
Type: "string",
Description: "The required token type.",
},
{
Name: "User",
OriginalName: "user",
Type: "string",
Description: "The optional user (name or ID) used for non-token based credentials.",
},
},
},
{
Name: "Root",
FQDTN: "tosca.datatypes.Root",
Fields: []model.Field{},
Name: "Root",
FQDTN: "tosca.datatypes.Root",
Description: "The TOSCA root Data Type all other TOSCA base Data Types derive from",
Fields: []model.Field{},
},
{
Name: "TimeInterval",
Expand Down Expand Up @@ -89,31 +96,37 @@ func TestParser_ParseTypes(t *testing.T) {
Name: "Credential",
FQDTN: "tosca.datatypes.Credential",
DerivedFrom: "TOSCARoot",
Description: "The Credential type is a complex TOSCA data Type used when describing authorization credentials used to access network accessible resources.",
Fields: []model.Field{
{
Name: "Keys",
OriginalName: "keys",
Type: "map[string]string",
Description: "The optional list of protocol-specific keys or assertions.",
},
{
Name: "Protocol",
OriginalName: "protocol",
Type: "string",
Description: "The optional protocol name.",
},
{
Name: "Token",
OriginalName: "token",
Type: "string",
Description: "The required token used as a credential for authorization or access to a networked resource.",
},
{
Name: "TokenType",
OriginalName: "token_type",
Type: "string",
Description: "The required token type.",
},
{
Name: "User",
OriginalName: "user",
Type: "string",
Description: "The optional user (name or ID) used for non-token based credentials.",
},
{
Name: "Validity",
Expand All @@ -123,9 +136,10 @@ func TestParser_ParseTypes(t *testing.T) {
},
},
{
Name: "TOSCARoot",
FQDTN: "tosca.datatypes.Root",
Fields: []model.Field{},
Name: "TOSCARoot",
FQDTN: "tosca.datatypes.Root",
Description: "The TOSCA root Data Type all other TOSCA base Data Types derive from",
Fields: []model.Field{},
},
{
Name: "ValidTimeInterval",
Expand Down Expand Up @@ -223,48 +237,56 @@ func TestParser_ParseTypes(t *testing.T) {
Name: "Credential",
FQDTN: "tosca.datatypes.Credential",
DerivedFrom: "Root",
Description: "The Credential type is a complex TOSCA data Type used when describing authorization credentials\nused to access network accessible resources.",
Fields: []model.Field{
{
Name: "Keys",
OriginalName: "keys",
Type: "map[string]string",
Description: "The optional list of protocol-specific keys or assertions.",
},
{
Name: "Protocol",
OriginalName: "protocol",
Type: "string",
Description: "The optional protocol name.",
},
{
Name: "Token",
OriginalName: "token",
Type: "string",
Description: "The required token used as a credential\nfor authorization or access to a networked resource.",
},
{
Name: "TokenType",
OriginalName: "token_type",
Type: "string",
Description: "The required token type.",
},
{
Name: "User",
OriginalName: "user",
Type: "string",
Description: "The optional user (name or ID) used for non-token based credentials.",
},
},
},
{
Name: "Root",
FQDTN: "tosca.datatypes.Root",
Fields: []model.Field{},
Name: "Root",
FQDTN: "tosca.datatypes.Root",
Description: "The TOSCA root Data Type all other TOSCA base Data Types derive from",
Fields: []model.Field{},
},
}, false},
{"TestParseExcludeFilters", &Parser{
ExcludePatterns: []string{`tosca\.datatypes\.Cred.*`, `tosca\.datatypes.TimeInterval`},
NameMappings: map[string]string{`tosca\.datatypes.TimeInterval`: "something.else.but.excluded.anyway"},
}, args{"testdata/normative-light.yaml"}, []model.DataType{
{
Name: "Root",
FQDTN: "tosca.datatypes.Root",
Fields: []model.Field{},
Name: "Root",
FQDTN: "tosca.datatypes.Root",
Description: "The TOSCA root Data Type all other TOSCA base Data Types derive from",
Fields: []model.Field{},
},
}, false},
}
Expand Down
9 changes: 6 additions & 3 deletions internal/pkg/parser/testdata/normative-light.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ data_types:

tosca.datatypes.Credential:
derived_from: tosca.datatypes.Root
description: >
The Credential type is a complex TOSCA data Type used when describing authorization credentials used to access network accessible resources.
description: |
The Credential type is a complex TOSCA data Type used when describing authorization credentials
used to access network accessible resources.
properties:
protocol:
type: string
Expand All @@ -27,7 +28,9 @@ data_types:
default: password
token:
type: string
description: The required token used as a credential for authorization or access to a networked resource.
description: |
The required token used as a credential
for authorization or access to a networked resource.
keys:
type: map
description: The optional list of protocol-specific keys or assertions.
Expand Down
2 changes: 1 addition & 1 deletion tdt2go.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ func getBuiltinTypes() []model.DataType {
DerivedFrom: "ScalarUnit",
},
{
Name: "ScalarUnitTim",
Name: "ScalarUnitTime",
FQDTN: "tosca:scalar-unit.time",
DerivedFrom: "ScalarUnit",
},
Expand Down
19 changes: 14 additions & 5 deletions testdata/golden/ChangePackage
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,25 @@ import (
)

// Credential is the generated representation of tosca.datatypes.Credential data type
//
// The Credential type is a complex TOSCA data Type used when describing authorization credentials used to access network accessible resources.
type Credential struct {
Root
Keys map[string]string `mapstructure:"keys" json:"keys,omitempty"`
Protocol string `mapstructure:"protocol" json:"protocol,omitempty"`
Token string `mapstructure:"token" json:"token,omitempty"`
TokenType string `mapstructure:"token_type" json:"token_type,omitempty"`
User string `mapstructure:"user" json:"user,omitempty"`
// The optional list of protocol-specific keys or assertions.
Keys map[string]string `mapstructure:"keys" json:"keys,omitempty"`
// The optional protocol name.
Protocol string `mapstructure:"protocol" json:"protocol,omitempty"`
// The required token used as a credential for authorization or access to a networked resource.
Token string `mapstructure:"token" json:"token,omitempty"`
// The required token type.
TokenType string `mapstructure:"token_type" json:"token_type,omitempty"`
// The optional user (name or ID) used for non-token based credentials.
User string `mapstructure:"user" json:"user,omitempty"`
}

// Root is the generated representation of tosca.datatypes.Root data type
//
// The TOSCA root Data Type all other TOSCA base Data Types derive from
type Root struct {
}

Expand Down

0 comments on commit 7a18d2d

Please sign in to comment.