Skip to content

Commit

Permalink
Merge pull request #6 from ing-bank/feature/linter
Browse files Browse the repository at this point in the history
Add linter to makefile, configuration and fix few linting issues
  • Loading branch information
survivorbat authored Sep 23, 2023
2 parents 0ca6aa9 + 18da68f commit 8d68db1
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 13 deletions.
86 changes: 86 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
linters-settings:
gocritic:
disabled-checks:
- "paramTypeCombine"
enabled-tags:
- "performance"
- "style"
- "diagnostic"
linters:
enable:
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- contextcheck
- cyclop
- decorder
- dogsled
- dupword
- durationcheck
- errcheck
- errname
- errorlint
- execinquery
- exhaustive
- exportloopref
- forbidigo
- ginkgolinter
- gocheckcompilerdirectives
- gochecknoinits
- gocognit
- goconst
- gocritic
- gocyclo
- goerr113
- gofmt
- gofumpt
- goheader
- goimports
- gomoddirectives
- gomodguard
- goprintffuncname
- gosec
- gosimple
- gosmopolitan
- govet
- grouper
- ifshort
- importas
- ineffassign
- interfacebloat
- interfacer
- ireturn
- loggercheck
- maintidx
- makezero
- mirror
- misspell
- musttag
- nakedret
- nestif
- nilerr
- nilnil
- nlreturn
- nonamedreturns
- nosprintfhostport
- paralleltest
- prealloc
- predeclared
- promlinter
- reassign
- rowserrcheck
- sqlclosecheck
- staticcheck
- tenv
- thelper
- tparallel
- typecheck
- unconvert
- unparam
- unused
- usestdlibvars
- wastedassign
- whitespace
- zerologlint
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,11 @@ test: fmt ## Run unit tests, alias: t

fmt: ## Format go code
@go mod tidy
@go fmt ./...
@gofumpt -l -w .

tools: ## Install extra tools for development
go install mvdan.cc/gofumpt@latest
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

lint: ## Lint the code locally
golangci-lint run
15 changes: 12 additions & 3 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/survivorbat/go-tsyncmap"
"reflect"
"regexp"
"strings"

"github.com/survivorbat/go-tsyncmap"
)

// typeCacheMap is used to easily fetch json keys from a type
Expand All @@ -20,6 +21,8 @@ type iKind[T any] interface {
}

// ensureConcrete ensures that the given value is a value and not a pointer, if it is, convert it to its element type
//
//nolint:ireturn // Does not matter in this context
func ensureConcrete[T iKind[T]](value T) T {
if value.Kind() == reflect.Ptr {
return ensureConcrete[T](value.Elem())
Expand All @@ -28,11 +31,14 @@ func ensureConcrete[T iKind[T]](value T) T {
return value
}

// errNotAStruct can be exported in the future if need be
var errNotAStruct = errors.New("object is not a struct")

// getFieldNameFromJson returns the field name from the json tag
func getFieldNameFromJson(object any, jsonKey string) (string, error) {
typeInfo := ensureConcrete(reflect.TypeOf(object))
if typeInfo.Kind() != reflect.Struct {
return "", errors.New("object is not a struct")
return "", errNotAStruct
}

typeName := typeNameOf(object)
Expand Down Expand Up @@ -62,6 +68,7 @@ func getFieldNameFromJson(object any, jsonKey string) (string, error) {
}

typeCacheMap.Store(typeName, typeCache)

return typeCache[jsonKey], nil
}

Expand Down Expand Up @@ -95,7 +102,7 @@ func injectLinks(registry LinkRegistry, object any, result map[string]any) {

// Replace the {name} with the actual value
matchString := fmt.Sprintf("{%s}", match[1])
linkInfo.Href = strings.Replace(linkInfo.Href, matchString, fmt.Sprintf("%v", urlValue), -1)
linkInfo.Href = strings.ReplaceAll(linkInfo.Href, matchString, fmt.Sprintf("%v", urlValue))
}

// Save the linkInfo in the object
Expand Down Expand Up @@ -159,6 +166,7 @@ func InjectLinks(registry LinkRegistry, object any) []byte {

var resultObject any

//nolint:exhaustive // Doesn't make sense to add more here
switch ensureConcrete(reflect.ValueOf(object)).Kind() {
case reflect.Slice, reflect.Struct, reflect.Array:
_ = json.Unmarshal(rawResponseJson, &resultObject)
Expand All @@ -170,5 +178,6 @@ func InjectLinks(registry LinkRegistry, object any) []byte {
}

finalResponse, _ := json.Marshal(resultObject)

return finalResponse
}
15 changes: 7 additions & 8 deletions generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package gohateoas
import (
"encoding/json"
"fmt"
"github.com/stretchr/testify/assert"
"net/http"
"reflect"
"testing"
"time"

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

type cupcake struct {
Expand Down Expand Up @@ -503,8 +504,7 @@ func TestInjectLinks_CreatesExpectedJsonWithDeeperSlice(t *testing.T) {
}

// empty is used as a dummy to make sure the if-statement in InjectLinks doesn't halt execution on no registered links
type empty struct {
}
type empty struct{}

func TestInjectLinks_ReturnsJsonOnUnknownType(t *testing.T) {
t.Parallel()
Expand Down Expand Up @@ -595,8 +595,7 @@ func TestInjectLinks_IgnoresOnNonStructSlices(t *testing.T) {
func TestInjectLinks_IgnoresIfRegistryIsEmpty(t *testing.T) {
t.Parallel()
// Arrange
type testType3 struct {
}
type testType3 struct{}

registry := NewLinkRegistry()

Expand Down Expand Up @@ -851,13 +850,12 @@ func BenchmarkInjectLinks(b *testing.B) {

registryTests := map[string]func() LinkRegistry{
// This test won't do much because there's an if-statement blocking execution, but it gives us a bit of insight
"no links": func() LinkRegistry {
return NewLinkRegistry()
},
"no links": NewLinkRegistry,

"3 links for fridge": func() LinkRegistry {
registry := NewLinkRegistry()
RegisterOn(registry, fridge{}, Self("/api/fridges", "Get this fridge"), Post("/api/fridges", "Create a new fridge"), Delete("/api/v1/fridges/{id}", "Delete a fridge"))

return registry
},

Expand All @@ -867,6 +865,7 @@ func BenchmarkInjectLinks(b *testing.B) {
RegisterOn(registry, vegetable{}, Self("/api/vegetables", "Get this vegetable"), Post("/api/vegetables", "Create a new vegetable"), Delete("/api/v1/vegetables/{id}", "Delete a vegetable"))
RegisterOn(registry, fruit{}, Self("/api/fruits", "Get this fruit"), Post("/api/fruits", "Create a new fruit"), Delete("/api/v1/fruits/{id}", "Delete a fruit"))
RegisterOn(registry, cake{}, Self("/api/cakes", "Get this cake"), Post("/api/cakes", "Create a new cake"), Delete("/api/v1/cakes/{id}", "Delete a cake"))

return registry
},
}
Expand Down
3 changes: 2 additions & 1 deletion registry_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package gohateoas

import (
"github.com/stretchr/testify/assert"
"net/http"
"testing"

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

func TestGetTypeName_ReturnsNameOnTypeA(t *testing.T) {
Expand Down

0 comments on commit 8d68db1

Please sign in to comment.