diff --git a/README.md b/README.md index 53fddad..2e6dd36 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,12 @@ The config file is a json file with the following structure: } } ``` -As output formats, you can choose between `cobertura` and `textfmt`. The first is described in the cobertura section and +As output formats, you can choose between `cobertura` and `textfmt`. The first is described in the cobertura section and the second is the default go coverage format. -Complexity only apply for the `cobertura` format. The complexity type can be either `cognitive` or `cyclomatic`. -The difference between these metrics is described in the cobertura section. +Complexity only applies for the `cobertura` format. The complexity type can be either `cognitive` or `cyclomatic`. +The difference between these metrics is described in the cobertura section. -The `SourcePath` is given relative to the working directory (starting with a `./`) or as absolute path. +The `SourcePath` is given relative to the working directory (starting with a `./`) or as absolute path. The `ExcludePaths` are paths that should be excluded from the coverage report. If a directory is in the exclude list, all files in this directory or subdirectory are excluded. They are given relative to the `SourcePath`. There are no white card or regex matching here. Thus, If you want to execlude more than one directory, you have to add them all to the list. The example above would exclude all files in the `vendor` directory in the working directory. @@ -57,7 +57,7 @@ The `Cleaner` part contains the filters that should be applied to the source cod ## The accuracy of `go test -coverprofile` The `go test -coverprofile` command is a great tool to get coverage information about your project. -However, it measures the coverage on a bock level. This means that if you function contains empty lines, only comments, +However, it measures the coverage on a block level. This means that if you function contains empty lines, only comments, or lines with only a closing bracket, they will be counted in line metrics. This project tries to solve this problem by using the `go/ast` package to determine the actual lines of code from the source. @@ -71,7 +71,7 @@ Thus, we add branch coverage on method and file level. Where such multi conditio There are parts of the source code that may not be included in the coverage report. At the moment, the following parts can be excluded: * Generated files - * Files that fellows [this convention](https://go.dev/s/generatedcode) are excluded + * Files that follow [this convention](https://go.dev/s/generatedcode) are excluded * None code lines * Empty lines * Lines that only contain a comment @@ -85,7 +85,7 @@ You can activate these filters by using the corresponding config values. # Cobertura Format The cobertura format is a widely used format for coverage reports. It is supported by many tools like Jenkins. -It is an XML format that contains the coverage information for each file and package. +It is an XML format that contains the coverage information for each file and package. Besides the coverage information, it also contains the complexity metrics for each function. The format is described [here](https://github.com/cobertura/cobertura/blob/master/cobertura/src/site/htdocs/xml/coverage-04.dtd). ## Cyclomatic Complexity vs Cognitive Complexity @@ -110,7 +110,7 @@ Cognitive Complexity aims to produce a measurement that will correlate more clos ### Summary -In summary, while Cyclomatic Complexity is a measure of the structural complexity of a program, Cognitive Complexity is a measure of how difficult a program is to understand by a human reader. +In summary, while Cyclomatic Complexity is a measure of the structural complexity of a program, Cognitive Complexity is a measure of how difficult a program is to understand by a human reader. Both are useful, but they serve different purposes and can lead to different conclusions about the code's quality. ## Others @@ -119,4 +119,4 @@ So far we are aware about two other projects that do something similar: * [gocover-cobertura](https://github.com/boumenot/gocover-cobertura) However, both of them focus on the coverage part and take over a big downsides of the `go test -coverprofile` command. -Further this project adds complexity metrics, more options to determine coverage, and branch coverage. \ No newline at end of file +Further this project adds complexity metrics, more options to determine coverage, and branch coverage. diff --git a/pkg/source/source.go b/pkg/source/source.go index 303aafb..1c1b939 100644 --- a/pkg/source/source.go +++ b/pkg/source/source.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" + "go/token" "golang.org/x/tools/go/packages" "github.com/Fabianexe/gocoverageplus/pkg/entity" @@ -73,6 +74,38 @@ func LoadSources(path string, excludePaths []string) (*entity.Project, error) { countMethods++ className := getClassName(fun) methodsMap[className] = append(methodsMap[className], method) + } else if gen, ok := decl.(*ast.GenDecl); ok && gen.Tok == token.VAR { + for _, spec := range gen.Specs { + if valueSpec, ok := spec.(*ast.ValueSpec); ok { + for _, value := range valueSpec.Values { + if funcLit, ok := value.(*ast.FuncLit); ok && len(valueSpec.Names) > 0 { + method := &entity.Method{ + Name: valueSpec.Names[0].Name, + Body: funcLit.Body, + File: pkg.Fset.File(value.Pos()), + } + + // start after the function declaration + startLine := pkg.Fset.Position(funcLit.Body.Lbrace).Line + 1 + endLine := pkg.Fset.Position(funcLit.End()).Line + if startLine >= endLine { + continue + } + + bV := &branchVisitor{ + fset: pkg.Fset, + } + + ast.Walk(bV, valueSpec) + + method.Tree = bV.getTree() + + countMethods++ + methodsMap["-"] = append(methodsMap["-"], method) + } + } + } + } } }