diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..aa619b0 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,27 @@ +version: 2.1 +orbs: + codecov: codecov/codecov@1.0.5 +jobs: + build: + docker: + - image: golang:1.13 + working_directory: /work + steps: + - checkout + - run: + name: Install golangci-lint + environment: + GOLANGCI_LINT_VERSION: 1.21.0 + command: | + wget -q https://github.com/golangci/golangci-lint/releases/download/v$GOLANGCI_LINT_VERSION/golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64.tar.gz \ + -O /tmp/golangci-lint.tar.gz + tar --strip-components=1 -C $GOPATH/bin -xzf /tmp/golangci-lint.tar.gz + golangci-lint --version + - run: + name: Code analysis + command: golangci-lint run -v --config .golangci.yml ./... + - run: + name: Test + command: go test -mod=readonly -v -race -count=1 -cover -coverprofile=profile.cov ./... + - codecov/upload: + file: /work/profile.cov \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..7f98d55 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,26 @@ +run: + deadline: 10m + +linters: + enable: + - dupl + - goconst + - gocyclo + - godox + - gosec + - interfacer + - lll + - maligned + - misspell + - prealloc + - stylecheck + - unconvert + - unparam + - errcheck + - golint + - gofmt + disable: [] + fast: false + +issues: + exclude-use-default: false diff --git a/.gometalinter.json b/.gometalinter.json deleted file mode 100644 index 9a240a0..0000000 --- a/.gometalinter.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Cyclo": 15 -} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c23e8fd..0000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: go - -go: -- '1.11' - -env: -- GO111MODULE=on - -install: -- GO111MODULE=off go get github.com/alecthomas/gometalinter -- GO111MODULE=off gometalinter --install --force -- go get github.com/mattn/goveralls - -script: -- go mod vendor -v -- GO111MODULE=off gometalinter --config=.gometalinter.json --deadline=10m . -- go test -mod=readonly -v -coverprofile=profile.cov ./... - -after_success: -- goveralls -coverprofile=profile.cov -service=travis-ci diff --git a/README.md b/README.md index f9c02a3..866287b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![Build Status](https://travis-ci.org/stoewer/go-strcase.svg?branch=master)](https://travis-ci.org/stoewer/go-strcase) -[![Coverage Status](https://coveralls.io/repos/github/stoewer/go-strcase/badge.svg?branch=master)](https://coveralls.io/github/stoewer/go-strcase?branch=master) +[![CircleCI](https://circleci.com/gh/stoewer/go-strcase/tree/master.svg?style=svg)](https://circleci.com/gh/stoewer/go-strcase/tree/master) +[![codecov](https://codecov.io/gh/stoewer/go-strcase/branch/master/graph/badge.svg)](https://codecov.io/gh/stoewer/go-strcase) [![GoDoc](https://godoc.org/github.com/stoewer/go-strcase?status.svg)](https://godoc.org/github.com/stoewer/go-strcase) --- @@ -42,16 +42,9 @@ Dependencies Run linters and unit tests -------------------------- -Since some of the linters ran by gometalinter don't support go modules yet, test dependencies have to be -loaded to the vendor directory first and gometalinter itself must run with disabled module support: +To run the static code analysis, linters and tests use the following commands: ``` -go mod vendor -GO111MODULE=off gometalinter --config=.gometalinter.json --deadline=10m . +golangci-lint run --config .golangci.yml ./... +go test ./... ``` - -To run the test use the following commands: - -``` -go test . -``` \ No newline at end of file diff --git a/camel.go b/camel.go index e79af7d..5c233cc 100644 --- a/camel.go +++ b/camel.go @@ -18,20 +18,20 @@ func LowerCamelCase(s string) string { } func camelCase(s string, upper bool) string { - s = strings.TrimSpace(SnakeCase(s)) + s = strings.TrimSpace(s) buffer := make([]rune, 0, len(s)) - var prev rune - for _, curr := range s { + stringIter(s, func(prev, curr, next rune) { if !isDelimiter(curr) { if isDelimiter(prev) || (upper && prev == 0) { buffer = append(buffer, toUpper(curr)) + } else if isLower(prev) { + buffer = append(buffer, curr) } else { buffer = append(buffer, toLower(curr)) } } - prev = curr - } + }) return string(buffer) } diff --git a/camel_test.go b/camel_test.go index e92e17f..a7bc5b8 100644 --- a/camel_test.go +++ b/camel_test.go @@ -15,6 +15,8 @@ func TestUpperCamelCase(t *testing.T) { "f": "F", "foo": "Foo", "fooBar": "FooBar", + "FooBarBla": "FooBarBla", + "foo_barBla": "FooBarBla", " foo_bar\n": "FooBar", " foo-bar\t": "FooBar", " foo bar\r": "FooBar", @@ -36,6 +38,8 @@ func TestLowerCamelCase(t *testing.T) { "F": "f", "foo": "foo", "FooBar": "fooBar", + "fooBarBla": "fooBarBla", + "foo_barBla": "fooBarBla", " foo_bar\n": "fooBar", " foo-bar\t": "fooBar", " foo bar\r": "fooBar", diff --git a/go.mod b/go.mod index bf56f48..6793c46 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,5 @@ module github.com/stoewer/go-strcase -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.2.2 -) +go 1.11 + +require github.com/stretchr/testify v1.4.0 diff --git a/go.sum b/go.sum index e03ee77..8fdee58 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,11 @@ -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/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/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/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/helper.go b/helper.go index 4d9ce71..ecad589 100644 --- a/helper.go +++ b/helper.go @@ -42,3 +42,30 @@ func isSpace(ch rune) bool { func isDelimiter(ch rune) bool { return ch == '-' || ch == '_' || isSpace(ch) } + +// iterFunc is a callback that is called fro a specific position in a string. Its arguments are the +// rune at the respective string position as well as the previous and the next rune. If curr is at the +// first position of the string prev is zero. If curr is at the end of the string next is zero. +type iterFunc func(prev, curr, next rune) + +// stringIter iterates over a string, invoking the callback for every single rune in the string. +func stringIter(s string, callback iterFunc) { + var prev rune + var curr rune + for _, next := range s { + if curr == 0 { + prev = curr + curr = next + continue + } + + callback(prev, curr, next) + + prev = curr + curr = next + } + + if len(s) > 0 { + callback(prev, curr, 0) + } +}