Skip to content

Commit

Permalink
Fix syntax parser, add more test
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitaksv committed Mar 27, 2022
1 parent c1c735d commit 4ceeba5
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 17 deletions.
13 changes: 8 additions & 5 deletions pkg/lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package lexer

import (
"regexp"
"strings"
)

var (
Expand Down Expand Up @@ -134,13 +135,15 @@ func (l Lexer) Replace(in []byte) []byte {
return in
}

func (l Lexer) Lex(in []byte) map[string]int {
if loc := l.Token.FindIndex(in); loc != nil {
return map[string]int{
string(in[loc[0]:loc[1]]): loc[1],
func (l Lexer) Lex(in []byte) map[int]string {
m := map[int]string{}
if locs := l.Token.FindAllIndex(in, -1); locs != nil {
for _, loc := range locs {
token := strings.TrimSpace(string(in[loc[0]:loc[1]]))
m[loc[1]] = token
}
}
return map[string]int{}
return m
}

func ExtractSplit(in []byte) []byte {
Expand Down
2 changes: 1 addition & 1 deletion pkg/lexer/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func TestLexer_Lex(t *testing.T) {
for _, lexers := range StartEndLexers {
var lexs []string
for _, lex := range lexers {
for token := range lex.Lex(in) {
for _, token := range lex.Lex(in) {
lexs = append(lexs, token)
}
}
Expand Down
43 changes: 43 additions & 0 deletions pkg/service/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,3 +352,46 @@ func TestService_PredefinedLangSettings(t *testing.T) {
assert.JSONEq(t, string(expected), string(bs))
}
}

func TestNewService(t *testing.T) {
srv := NewService(nil)
assert.NotNil(t, srv)
srv = NewService(zap.NewNop())
assert.NotNil(t, srv)
}

func TestService_Gen(t *testing.T) {
t.Run("Empty req", func(t *testing.T) {
req := &GenRequest{}
_, err := NewService(nil).Gen(context.Background(), req)
assert.Error(t, err)
})
t.Run("Empty req lang config", func(t *testing.T) {
req := &GenRequest{
Config: &Config{
LangSettings: nil,
},
Tmpl: []byte(`1`),
Data: []byte(`1`),
}
_, err := NewService(nil).Gen(context.Background(), req)
assert.Error(t, err)
})
t.Run("Empty req lang configMap", func(t *testing.T) {
req := &GenRequest{
Config: &Config{
LangSettings: &LangSettings{
ConfigMapping: nil,
Code: "test",
Name: "Test",
FileExtension: ".test",
SplitObjectByFiles: false,
},
},
Tmpl: []byte(`1`),
Data: []byte(`1`),
}
_, err := NewService(nil).Gen(context.Background(), req)
assert.Error(t, err)
})
}
25 changes: 15 additions & 10 deletions pkg/syntax/syntax.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,25 @@ func Validate(in []byte) error {
}

startSplitLex := lexer.LexBeginSplit.Lex(in)
if len(startSplitLex) > 1 {
return errors.Wrapf(ErrSyntax, "have only one '%s' tag", printLex(startSplitLex))
}
endSplitLex := lexer.LexEndSplit.Lex(in)
if len(endSplitLex) > 1 {
return errors.Wrapf(ErrSyntax, "have only one '%s' tag", printLex(endSplitLex))
if len(startSplitLex) > 1 || len(endSplitLex) > 1 {
tag := printLex(startSplitLex)
if tag == "" {
tag = printLex(endSplitLex)
}
return errors.Wrapf(ErrSyntax, "have only one '%s' tag", tag)
}

return nil
}

func Parse(in []byte) ([]byte, error) {
for _, l := range lexer.Lexers {
in = l.Replace(in)
}
if err := Validate(in); err != nil {
return nil, err
}
for _, l := range lexer.Lexers {
in = l.Replace(in)
}

return in, nil
}
Expand All @@ -55,15 +56,19 @@ func ParseWithSplit(in []byte) ([]byte, []byte, error) {
return in, splitted, nil
}

func printLex(lex map[string]int) string {
func printLex(lex map[int]string) string {
token := ""
maxIdx := 0
for t, i := range lex {
for i, t := range lex {
if maxIdx == 0 || i >= maxIdx {
token = t
maxIdx = i
}
}

if token == "" {
return ""
}

return fmt.Sprintf("%s:%d", token, maxIdx)
}
140 changes: 139 additions & 1 deletion pkg/syntax/syntax_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package syntax

import "testing"
import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestValidate(t *testing.T) {
tests := []struct {
Expand Down Expand Up @@ -47,3 +51,137 @@ func TestValidate(t *testing.T) {
})
}
}

func TestParse(t *testing.T) {
tmpl := []byte(`
package main
{{ SPLIT }}
type {{ Name.PascalCase }} struct {
{{ Properties }}
{{ Name.PascalCase }} {{ Type.Doc }}
{{ /Properties }}
}
{{ /SPLIT }}
`)
outExpected := []byte(`
package main
{{ SPLIT }}
type {{ .Key.PascalCase }} struct {
{{- range .Properties }}
{{ .Key.PascalCase }} {{ .Type.Doc }}
{{- end }}
}
{{ /SPLIT }}
`)
out, err := Parse(tmpl)
assert.NoError(t, err)
assert.Equal(t, string(outExpected), string(out))
}

func TestParse_Error(t *testing.T) {
tmpl := []byte(`
package main
type {{ Name.PascalCase }} struct {
{{ Properties }}
{{ Name.PascalCase }} {{ Type.Doc }}
}
`)
_, err := Parse(tmpl)
assert.Error(t, err)
}

func TestParseWithSplit(t *testing.T) {
tmpl := []byte(`
package main
{{ SPLIT }}
type {{ Name.PascalCase }} struct {
{{ Properties }}
{{ Name.PascalCase }} {{ Type.Doc }}
{{ /Properties }}
}
{{ /SPLIT }}
`)
outExpected := []byte(`
package main
type {{ .Key.PascalCase }} struct {
{{- range .Properties }}
{{ .Key.PascalCase }} {{ .Type.Doc }}
{{- end }}
}
`)
splittedExpected := []byte(`
type {{ .Key.PascalCase }} struct {
{{- range .Properties }}
{{ .Key.PascalCase }} {{ .Type.Doc }}
{{- end }}
}
`)
out, splitted, err := ParseWithSplit(tmpl)
assert.NoError(t, err)
assert.Equal(t, string(outExpected), string(out))
assert.Equal(t, string(splittedExpected), string(splitted))
}

func TestParseWithSplit_Error(t *testing.T) {
tmpl := []byte(`{{ SPLIT }}`)

_, _, err := ParseWithSplit(tmpl)
assert.Error(t, err)

tmpl = []byte(`
{{ SPLIT }}
{{ SPLIT }}
{{ /SPLIT }}
{{ /SPLIT }}
`)

_, _, err = ParseWithSplit(tmpl)
assert.Error(t, err)

tmpl = []byte(`
{{ /SPLIT }}
{{ /SPLIT }}
{{ SPLIT }}
{{ SPLIT }}
`)

_, _, err = ParseWithSplit(tmpl)
assert.Error(t, err)

tmpl = []byte(`
{{ /SPLIT }}
{{ SPLIT }}
{{ SPLIT }}
`)

_, _, err = ParseWithSplit(tmpl)
assert.Error(t, err)

tmpl = []byte(`
{{ SPLIT }}
{{ SPLIT }}
{{ /SPLIT }}
`)

_, _, err = ParseWithSplit(tmpl)
assert.Error(t, err)
}

func Test_printLex(t *testing.T) {
m := map[int]string{
0: "qwerty",
1: "qwerty",
}
assert.Equal(t, "qwerty:1", printLex(m))
m = map[int]string{}
assert.Equal(t, "", printLex(m))
}

0 comments on commit 4ceeba5

Please sign in to comment.