{"id":17720203,"url":"https://github.com/uudashr/gocognit","last_synced_at":"2025-05-14T00:05:53.023Z","repository":{"id":36335235,"uuid":"210177781","full_name":"uudashr/gocognit","owner":"uudashr","description":"Calculates cognitive complexities of functions (and methods) in Go source code. (Golang cognitive complexity)","archived":false,"fork":false,"pushed_at":"2024-07-31T06:39:31.000Z","size":64,"stargazers_count":329,"open_issues_count":0,"forks_count":17,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-07-31T07:58:21.267Z","etag":null,"topics":["cognitive","complexity","go","golang","linter","metrics","tool"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uudashr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-22T16:21:25.000Z","updated_at":"2024-07-31T06:39:24.000Z","dependencies_parsed_at":"2024-07-26T05:27:57.061Z","dependency_job_id":"fc1df335-d728-4987-b636-0bc145e7564d","html_url":"https://github.com/uudashr/gocognit","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uudashr%2Fgocognit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uudashr%2Fgocognit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uudashr%2Fgocognit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uudashr%2Fgocognit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uudashr","download_url":"https://codeload.github.com/uudashr/gocognit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247097986,"owners_count":20883128,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cognitive","complexity","go","golang","linter","metrics","tool"],"created_at":"2024-10-25T15:26:30.548Z","updated_at":"2025-04-04T00:05:58.301Z","avatar_url":"https://github.com/uudashr.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"[![Go Reference](https://pkg.go.dev/badge/github.com/uudashr/gocognit.svg)](https://pkg.go.dev/github.com/uudashr/gocognit)\n[![go-recipes](https://raw.githubusercontent.com/nikolaydubina/go-recipes/main/badge.svg?raw=true)](https://github.com/nikolaydubina/go-recipes)\n\n# Gocognit\nGocognit calculates cognitive complexities of functions (and methods) in Go source code. A measurement of how hard does the code is intuitively to understand.\n\n## Understanding the complexity\n\nGiven code using `if` statement,\n```go\nfunc GetWords(number int) string {\n    if number == 1 {            // +1\n        return \"one\"\n    } else if number == 2 {     // +1\n        return \"a couple\"\n    } else if number == 3 {     // +1\n        return \"a few\"\n    } else {                    // +1\n        return \"lots\"\n    }\n} // Cognitive complexity = 4\n```\n\nAbove code can be refactored using `switch` statement,\n```go\nfunc GetWords(number int) string {\n    switch number {             // +1\n        case 1:\n            return \"one\"\n        case 2:\n            return \"a couple\"\n        case 3:\n            return \"a few\"\n        default:\n            return \"lots\"\n    }\n} // Cognitive complexity = 1\n```\n\nAs you see above codes are the same, but the second code are easier to understand, that is why the cognitive complexity score are lower compare to the first one.\n\n## Comparison with cyclomatic complexity\n\n### Example 1\n#### Cyclomatic complexity\n```go\nfunc GetWords(number int) string {      // +1\n    switch number {\n        case 1:                         // +1\n            return \"one\"\n        case 2:                         // +1\n            return \"a couple\"\n        case 3:                         // +1\n             return \"a few\"\n        default:\n             return \"lots\"\n    }\n} // Cyclomatic complexity = 4\n```\n\n####  Cognitive complexity\n```go\nfunc GetWords(number int) string {\n    switch number {                     // +1\n        case 1:\n            return \"one\"\n        case 2:\n            return \"a couple\"\n        case 3:\n            return \"a few\"\n        default:\n            return \"lots\"\n    }\n} // Cognitive complexity = 1\n```\n\nCognitive complexity give lower score compare to cyclomatic complexity.\n\n### Example 2\n#### Cyclomatic complexity\n```go\nfunc SumOfPrimes(max int) int {         // +1\n    var total int\n\nOUT:\n    for i := 1; i \u003c max; i++ {          // +1\n        for j := 2; j \u003c i; j++ {        // +1\n            if i%j == 0 {               // +1\n                continue OUT\n            }\n        }\n        total += i\n    }\n\n    return total\n} // Cyclomatic complexity = 4\n```\n\n#### Cognitive complexity\n```go\nfunc SumOfPrimes(max int) int {\n    var total int\n\nOUT:\n    for i := 1; i \u003c max; i++ {          // +1\n        for j := 2; j \u003c i; j++ {        // +2 (nesting = 1)\n            if i%j == 0 {               // +3 (nesting = 2)\n                continue OUT            // +1\n            }\n        }\n        total += i\n    }\n\n    return total\n} // Cognitive complexity = 7\n```\n\nCognitive complexity give higher score compare to cyclomatic complexity.\n\n## Rules\n\nThe cognitive complexity of a function is calculated according to the\nfollowing rules:\n\u003e Note: these rules are specific for Go, please see the [original whitepaper](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) for more complete reference.\n\n### Increments\nThere is an increment for each of the following:\n1. `if`, `else if`, `else`\n2. `switch`, `select`\n3. `for`\n4. `goto` LABEL, `break` LABEL, `continue` LABEL\n5. sequence of binary logical operators\n6. each method in a recursion cycle\n\n### Nesting level\nThe following structures increment the nesting level:\n1. `if`, `else if`, `else`\n2. `switch`, `select`\n3. `for`\n4. function literal or lambda\n\n### Nesting increments\nThe following structures receive a nesting increment commensurate with their nested depth inside nesting structures:\n1. `if`\n2. `switch`, `select`\n3. `for`\n\n## Installation\n\n```shell\ngo install github.com/uudashr/gocognit/cmd/gocognit@latest\n```\n\nor \n\n```shell\ngo get github.com/uudashr/gocognit/cmd/gocognit\n```\n\n## Usage\n\n```\n$ gocognit\nCalculate cognitive complexities of Go functions.\n\nUsage:\n\n  gocognit [\u003cflag\u003e ...] \u003cGo file or directory\u003e ...\n\nFlags:\n\n  -over N       show functions with complexity \u003e N only\n                and return exit code 1 if the output is non-empty\n  -top N        show the top N most complex functions only\n  -avg          show the average complexity over all functions,\n                not depending on whether -over or -top are set\n  -test         indicates whether test files should be included\n  -json         encode the output as JSON\n  -d \t        enable diagnostic output\n  -f format     string the format to use\n                (default \"{{.Complexity}} {{.PkgName}} {{.FuncName}} {{.Pos}}\")\n  -ignore expr  ignore files matching the given regexp\n\nThe (default) output fields for each line are:\n\n  \u003ccomplexity\u003e \u003cpackage\u003e \u003cfunction\u003e \u003cfile:row:column\u003e\n\nThe (default) output fields for each line are:\n\n  {{.Complexity}} {{.PkgName}} {{.FuncName}} {{.Pos}}\n\nor equal to \u003ccomplexity\u003e \u003cpackage\u003e \u003cfunction\u003e \u003cfile:row:column\u003e\n\nThe struct being passed to the template is:\n\n  type Stat struct {\n    PkgName     string\n    FuncName    string\n    Complexity  int\n    Pos         token.Position\n    Diagnostics []Diagnostics\n  }\n\n  type Diagnostic struct {\n    Inc     string\n    Nesting int\n    Text    string\n    Pos     DiagnosticPosition\n  }\n\n  type DiagnosticPosition struct {\n    Offset int\n    Line   int\n    Column int\n  }\n```\n\nExamples:\n\n```\n$ gocognit .\n$ gocognit main.go\n$ gocognit -top 10 src/\n$ gocognit -over 25 docker\n$ gocognit -avg .\n$ gocognit -ignore \"_test|testdata\" .\n```\n\nThe output fields for each line are:\n```\n\u003ccomplexity\u003e \u003cpackage\u003e \u003cfunction\u003e \u003cfile:row:column\u003e\n```\n\n## Ignore individual functions\nIgnore individual functions by specifying `gocognit:ignore` directive.\n```go\n//gocognit:ignore\nfunc IgnoreMe() {\n    // ...\n}\n```\n\n## Diagnostic\nTo understand how the complexity are calculated, we can enable the diagnostic by using `-d` flag.\n\nExample:\n```shell\n$ gocognit -json -d .\n```\n\nIt will show the diagnostic output in JSON format\n\u003cdetails\u003e\n\n\u003csummary\u003eJSON Output\u003c/summary\u003e\n    \n```json\n[\n    {\n        \"PkgName\": \"prime\",\n        \"FuncName\": \"SumOfPrimes\",\n        \"Complexity\": 7,\n        \"Pos\": {\n            \"Filename\": \"prime.go\",\n            \"Offset\": 15,\n            \"Line\": 3,\n            \"Column\": 1\n        },\n        \"Diagnostics\": [\n            {\n                \"Inc\": 1,\n                \"Text\": \"for\",\n                \"Pos\": {\n                    \"Offset\": 69,\n                    \"Line\": 7,\n                    \"Column\": 2\n                }\n            },\n            {\n                \"Inc\": 2,\n                \"Nesting\": 1,\n                \"Text\": \"for\",\n                \"Pos\": {\n                    \"Offset\": 104,\n                    \"Line\": 8,\n                    \"Column\": 3\n                }\n            },\n            {\n                \"Inc\": 3,\n                \"Nesting\": 2,\n                \"Text\": \"if\",\n                \"Pos\": {\n                    \"Offset\": 152,\n                    \"Line\": 9,\n                    \"Column\": 4\n                }\n            },\n            {\n                \"Inc\": 1,\n                \"Text\": \"continue\",\n                \"Pos\": {\n                    \"Offset\": 190,\n                    \"Line\": 10,\n                    \"Column\": 5\n                }\n            }\n        ]\n    }\n]\n```\n\u003c/details\u003e\n\n## Related project\n- [Gocyclo](https://github.com/fzipp/gocyclo) where the code are based on.\n- [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) white paper by G. Ann Campbell.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuudashr%2Fgocognit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuudashr%2Fgocognit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuudashr%2Fgocognit/lists"}