aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/yagipy
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/yagipy')
-rw-r--r--vendor/github.com/yagipy/maintidx/.gitignore2
-rw-r--r--vendor/github.com/yagipy/maintidx/LICENSE21
-rw-r--r--vendor/github.com/yagipy/maintidx/Makefile2
-rw-r--r--vendor/github.com/yagipy/maintidx/README.md45
-rw-r--r--vendor/github.com/yagipy/maintidx/go.mod11
-rw-r--r--vendor/github.com/yagipy/maintidx/go.sum28
-rw-r--r--vendor/github.com/yagipy/maintidx/maintidx.go63
-rw-r--r--vendor/github.com/yagipy/maintidx/pkg/cyc/cyc.go36
-rw-r--r--vendor/github.com/yagipy/maintidx/pkg/halstvol/halstvol.go71
-rw-r--r--vendor/github.com/yagipy/maintidx/pkg/halstvol/handle.go151
-rw-r--r--vendor/github.com/yagipy/maintidx/visitor.go77
11 files changed, 507 insertions, 0 deletions
diff --git a/vendor/github.com/yagipy/maintidx/.gitignore b/vendor/github.com/yagipy/maintidx/.gitignore
new file mode 100644
index 000000000..a676215fa
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/.gitignore
@@ -0,0 +1,2 @@
+.idea
+bin
diff --git a/vendor/github.com/yagipy/maintidx/LICENSE b/vendor/github.com/yagipy/maintidx/LICENSE
new file mode 100644
index 000000000..b94c2ede8
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Hiroyuki Yagihashi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/github.com/yagipy/maintidx/Makefile b/vendor/github.com/yagipy/maintidx/Makefile
new file mode 100644
index 000000000..14b8fc979
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/Makefile
@@ -0,0 +1,2 @@
+build:
+ go build -o bin/maintidx ./cmd/maintidx
diff --git a/vendor/github.com/yagipy/maintidx/README.md b/vendor/github.com/yagipy/maintidx/README.md
new file mode 100644
index 000000000..8d5e26df0
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/README.md
@@ -0,0 +1,45 @@
+# maintidx
+`maintidx` measures the maintainability index of each function.
+https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning
+
+## Installation
+### Go version < 1.16
+```shell
+go get -u github.com/yagipy/maintidx/cmd/maintidx
+```
+
+### Go version 1.16+
+```shell
+go install github.com/yagipy/maintidx/cmd/maintidx
+```
+
+## Usage
+### standalone
+```shell
+maintidx ./...
+```
+
+### with go run
+No installation required
+```shell
+go run github.com/yagipy/maintidx/cmd/maintidx ./...
+```
+
+### with go vet
+```shell
+go vet -vettool=`which maintidx` ./...
+```
+
+## Flag
+```shell
+Flags:
+ -under int
+ show functions with maintainability index < N only. (default 20)
+```
+
+## TODO
+- [ ] Setup execute env on container
+- [ ] Impl cyc.Cyc.Calc()
+- [ ] Move maintidx.Visitor.PrintHalstVol to halstval package
+- [ ] Consider the necessity of halstvol.incrIfAllTrue
+- [ ] Test under pkg file
diff --git a/vendor/github.com/yagipy/maintidx/go.mod b/vendor/github.com/yagipy/maintidx/go.mod
new file mode 100644
index 000000000..6f216f80c
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/go.mod
@@ -0,0 +1,11 @@
+module github.com/yagipy/maintidx
+
+go 1.17
+
+require golang.org/x/tools v0.1.8
+
+require (
+ golang.org/x/mod v0.5.1 // indirect
+ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect
+ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
+)
diff --git a/vendor/github.com/yagipy/maintidx/go.sum b/vendor/github.com/yagipy/maintidx/go.sum
new file mode 100644
index 000000000..b0bad9f67
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/go.sum
@@ -0,0 +1,28 @@
+github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
+golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
+golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/vendor/github.com/yagipy/maintidx/maintidx.go b/vendor/github.com/yagipy/maintidx/maintidx.go
new file mode 100644
index 000000000..31ad9ca0c
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/maintidx.go
@@ -0,0 +1,63 @@
+package maintidx
+
+import (
+ "go/ast"
+ "go/token"
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+const doc = "maintidx measures the maintainability index of each function."
+
+var Analyzer = &analysis.Analyzer{
+ Name: "maintidx",
+ Doc: doc,
+ Run: run,
+ Requires: []*analysis.Analyzer{
+ inspect.Analyzer,
+ },
+}
+
+var under int
+
+func init() {
+ Analyzer.Flags.IntVar(&under, "under", 20, "show functions with maintainability index < N only.")
+}
+
+func run(pass *analysis.Pass) (interface{}, error) {
+ i := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+
+ nodeFilter := []ast.Node{
+ (*ast.FuncDecl)(nil),
+ }
+
+ i.Preorder(nodeFilter, func(n ast.Node) {
+ switch n := n.(type) {
+ case *ast.FuncDecl:
+ v := analyze(n)
+
+ v.Coef.Cyc.Calc()
+ v.Coef.HalstVol.Calc()
+ v.calc(loc(pass.Fset, n))
+ if v.MaintIdx < under {
+ pass.Reportf(n.Pos(), "Function name: %v, Cyclomatic Complexity: %v, Halstead Volume: %0.2f, Maintainability Index: %v", n.Name, v.Coef.Cyc.Val, v.Coef.HalstVol.Val, v.MaintIdx)
+ }
+ }
+ })
+
+ return nil, nil
+}
+
+func analyze(n ast.Node) Visitor {
+ v := NewVisitor()
+ ast.Walk(v, n)
+ return *v
+}
+
+func loc(fs *token.FileSet, n *ast.FuncDecl) int {
+ f := fs.File(n.Pos())
+ startLine := f.Line(n.Pos())
+ endLine := f.Line(n.End())
+ return endLine - startLine + 1
+}
diff --git a/vendor/github.com/yagipy/maintidx/pkg/cyc/cyc.go b/vendor/github.com/yagipy/maintidx/pkg/cyc/cyc.go
new file mode 100644
index 000000000..9ea009106
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/pkg/cyc/cyc.go
@@ -0,0 +1,36 @@
+package cyc
+
+import (
+ "go/ast"
+ "go/token"
+)
+
+type Cyc struct {
+ Val int
+ Coef Coef
+}
+
+type Coef struct{}
+
+func (c *Cyc) Analyze(n ast.Node) {
+ switch n := n.(type) {
+ case *ast.IfStmt, *ast.ForStmt, *ast.RangeStmt:
+ c.Val++
+ case *ast.CaseClause:
+ if n.List != nil {
+ c.Val++
+ }
+ case *ast.CommClause:
+ if n.Comm != nil {
+ c.Val++
+ }
+ case *ast.BinaryExpr:
+ if n.Op == token.LAND || n.Op == token.LOR {
+ c.Val++
+ }
+ }
+}
+
+// TODO: Implement
+func (c *Cyc) Calc() {
+}
diff --git a/vendor/github.com/yagipy/maintidx/pkg/halstvol/halstvol.go b/vendor/github.com/yagipy/maintidx/pkg/halstvol/halstvol.go
new file mode 100644
index 000000000..f0212759b
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/pkg/halstvol/halstvol.go
@@ -0,0 +1,71 @@
+package halstvol
+
+import (
+ "go/ast"
+ "math"
+)
+
+type HalstVol struct {
+ Val float64
+ Coef Coef
+}
+
+type Coef struct {
+ Opt map[string]int
+ Opd map[string]int
+}
+
+func (v *HalstVol) Analyze(n ast.Node) {
+ switch n := n.(type) {
+ case *ast.FuncDecl, *ast.GenDecl:
+ v.handleDecl(n)
+ case *ast.ParenExpr, *ast.IndexExpr, *ast.SliceExpr, *ast.TypeAssertExpr, *ast.CallExpr, *ast.StarExpr, *ast.UnaryExpr, *ast.BinaryExpr, *ast.KeyValueExpr:
+ v.handleExpr(n)
+ case *ast.BasicLit, *ast.CompositeLit:
+ v.handleLit(n)
+ case *ast.Ident:
+ v.handleIdent(n)
+ case *ast.Ellipsis:
+ incrIfAllTrue(v.Coef.Opt, "...", []bool{n.Ellipsis.IsValid()})
+ case *ast.FuncType:
+ incrIfAllTrue(v.Coef.Opt, "func", []bool{n.Func.IsValid()})
+ v.Coef.Opt["()"]++
+ case *ast.ChanType:
+ incrIfAllTrue(v.Coef.Opt, "chan", []bool{n.Begin.IsValid()})
+ incrIfAllTrue(v.Coef.Opt, "<-", []bool{n.Arrow.IsValid()})
+ case *ast.SendStmt, *ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt, *ast.DeferStmt, *ast.ReturnStmt, *ast.BranchStmt, *ast.BlockStmt, *ast.IfStmt, *ast.SwitchStmt, *ast.SelectStmt, *ast.ForStmt, *ast.RangeStmt:
+ v.handleStmt(n)
+ case *ast.CaseClause:
+ v.handleCaseClause(n)
+ }
+}
+
+func (v *HalstVol) Calc() {
+ distOpt := len(v.Coef.Opt)
+ distOpd := len(v.Coef.Opd)
+
+ var sumOpt, sumOpd int
+
+ for _, val := range v.Coef.Opt {
+ sumOpt += val
+ }
+
+ for _, val := range v.Coef.Opd {
+ sumOpd += val
+ }
+
+ vocab := distOpt + distOpd
+ length := sumOpt + sumOpd
+
+ v.Val = float64(length) * math.Log2(float64(vocab))
+}
+
+// TODO: Consider the necessity
+func incrIfAllTrue(coef map[string]int, sym string, cond []bool) {
+ for _, ok := range cond {
+ if !ok {
+ return
+ }
+ }
+ coef[sym]++
+}
diff --git a/vendor/github.com/yagipy/maintidx/pkg/halstvol/handle.go b/vendor/github.com/yagipy/maintidx/pkg/halstvol/handle.go
new file mode 100644
index 000000000..9f5e33500
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/pkg/halstvol/handle.go
@@ -0,0 +1,151 @@
+package halstvol
+
+import "go/ast"
+
+func (v *HalstVol) handleDecl(decl ast.Node) {
+ switch n := decl.(type) {
+ case *ast.FuncDecl:
+ if n.Recv == nil {
+ // In the case of receiver functions, the function name is incremented in *ast.Ident
+ v.Coef.Opt[n.Name.Name]++
+ } else {
+ v.Coef.Opt["()"]++
+ }
+ case *ast.GenDecl:
+ if n.Lparen.IsValid() && n.Rparen.IsValid() {
+ v.Coef.Opt["()"]++
+ }
+
+ if n.Tok.IsOperator() {
+ v.Coef.Opt[n.Tok.String()]++
+ } else {
+ v.Coef.Opd[n.Tok.String()]++
+ }
+ }
+}
+
+func (v *HalstVol) handleIdent(ident *ast.Ident) {
+ if ident.Obj == nil {
+ v.Coef.Opt[ident.Name]++
+ } else {
+ if ident.Obj.Kind.String() != "func" {
+ v.Coef.Opd[ident.Name]++
+ }
+ }
+}
+
+func (v *HalstVol) handleLit(lit ast.Node) {
+ switch n := lit.(type) {
+ case *ast.BasicLit:
+ if n.Kind.IsLiteral() {
+ v.Coef.Opd[n.Value]++
+ } else {
+ v.Coef.Opt[n.Value]++
+ }
+ case *ast.CompositeLit:
+ incrIfAllTrue(v.Coef.Opt, "{}", []bool{n.Lbrace.IsValid(), n.Rbrace.IsValid()})
+ }
+}
+
+func (v *HalstVol) handleExpr(expr ast.Node) {
+ switch n := expr.(type) {
+ case *ast.ParenExpr:
+ incrIfAllTrue(v.Coef.Opt, "()", []bool{n.Lparen.IsValid(), n.Rparen.IsValid()})
+ case *ast.IndexExpr:
+ incrIfAllTrue(v.Coef.Opt, "{}", []bool{n.Lbrack.IsValid(), n.Rbrack.IsValid()})
+ case *ast.SliceExpr:
+ incrIfAllTrue(v.Coef.Opt, "[]", []bool{n.Lbrack.IsValid(), n.Rbrack.IsValid()})
+ case *ast.TypeAssertExpr:
+ incrIfAllTrue(v.Coef.Opt, "()", []bool{n.Lparen.IsValid(), n.Rparen.IsValid()})
+ case *ast.CallExpr:
+ incrIfAllTrue(v.Coef.Opt, "()", []bool{n.Lparen.IsValid(), n.Rparen.IsValid()})
+ incrIfAllTrue(v.Coef.Opt, "...", []bool{n.Ellipsis != 0})
+ case *ast.StarExpr:
+ incrIfAllTrue(v.Coef.Opt, "*", []bool{n.Star.IsValid()})
+ case *ast.UnaryExpr:
+ if n.Op.IsOperator() {
+ v.Coef.Opt[n.Op.String()]++
+ } else {
+ v.Coef.Opd[n.Op.String()]++
+ }
+ case *ast.BinaryExpr:
+ v.Coef.Opt[n.Op.String()]++
+ case *ast.KeyValueExpr:
+ incrIfAllTrue(v.Coef.Opt, ":", []bool{n.Colon.IsValid()})
+ }
+}
+
+func (v *HalstVol) handleStmt(stmt ast.Node) {
+ switch n := stmt.(type) {
+ case *ast.SendStmt:
+ incrIfAllTrue(v.Coef.Opt, "<-", []bool{n.Arrow.IsValid()})
+ case *ast.IncDecStmt:
+ incrIfAllTrue(v.Coef.Opt, n.Tok.String(), []bool{n.Tok.IsOperator()})
+ case *ast.AssignStmt:
+ if n.Tok.IsOperator() {
+ v.Coef.Opt[n.Tok.String()]++
+ }
+ case *ast.GoStmt:
+ if n.Go.IsValid() {
+ v.Coef.Opt["go"]++
+ }
+ case *ast.DeferStmt:
+ if n.Defer.IsValid() {
+ v.Coef.Opt["defer"]++
+ }
+ case *ast.ReturnStmt:
+ if n.Return.IsValid() {
+ v.Coef.Opt["return"]++
+ }
+ case *ast.BranchStmt:
+ if n.Tok.IsOperator() {
+ v.Coef.Opt[n.Tok.String()]++
+ } else {
+ v.Coef.Opd[n.Tok.String()]++
+ }
+ case *ast.BlockStmt:
+ if n.Lbrace.IsValid() && n.Rbrace.IsValid() {
+ v.Coef.Opt["{}"]++
+ }
+ case *ast.IfStmt:
+ if n.If.IsValid() {
+ v.Coef.Opt["if"]++
+ }
+ if n.Else != nil {
+ v.Coef.Opt["else"]++
+ }
+ case *ast.SwitchStmt:
+ if n.Switch.IsValid() {
+ v.Coef.Opt["switch"]++
+ }
+ case *ast.SelectStmt:
+ if n.Select.IsValid() {
+ v.Coef.Opt["select"]++
+ }
+ case *ast.ForStmt:
+ if n.For.IsValid() {
+ v.Coef.Opt["for"]++
+ }
+ case *ast.RangeStmt:
+ if n.For.IsValid() {
+ v.Coef.Opt["for"]++
+ }
+ if n.Key != nil {
+ if n.Tok.IsOperator() {
+ v.Coef.Opt[n.Tok.String()]++
+ } else {
+ v.Coef.Opd[n.Tok.String()]++
+ }
+ }
+ v.Coef.Opt["range"]++
+ }
+}
+
+func (v *HalstVol) handleCaseClause(cc *ast.CaseClause) {
+ if cc.List == nil {
+ v.Coef.Opt["default"]++
+ }
+ if cc.Colon.IsValid() {
+ v.Coef.Opt[":"]++
+ }
+}
diff --git a/vendor/github.com/yagipy/maintidx/visitor.go b/vendor/github.com/yagipy/maintidx/visitor.go
new file mode 100644
index 000000000..e6f74c50d
--- /dev/null
+++ b/vendor/github.com/yagipy/maintidx/visitor.go
@@ -0,0 +1,77 @@
+package maintidx
+
+import (
+ "github.com/yagipy/maintidx/pkg/cyc"
+ "github.com/yagipy/maintidx/pkg/halstvol"
+ "go/ast"
+ "math"
+ "sort"
+)
+
+type Visitor struct {
+ MaintIdx int
+ Coef Coef
+}
+
+var _ ast.Visitor = &Visitor{}
+
+type Coef struct {
+ Cyc cyc.Cyc
+ HalstVol halstvol.HalstVol
+}
+
+func NewVisitor() *Visitor {
+ return &Visitor{
+ MaintIdx: 0,
+ Coef: Coef{
+ Cyc: cyc.Cyc{
+ Val: 1,
+ Coef: cyc.Coef{},
+ },
+ HalstVol: halstvol.HalstVol{
+ Val: 0.0,
+ Coef: halstvol.Coef{
+ Opt: map[string]int{},
+ Opd: map[string]int{},
+ },
+ },
+ },
+ }
+}
+
+func (v *Visitor) Visit(n ast.Node) ast.Visitor {
+ v.Coef.Cyc.Analyze(n)
+ v.Coef.HalstVol.Analyze(n)
+ return v
+}
+
+// Calc https://docs.microsoft.com/ja-jp/archive/blogs/codeanalysis/maintainability-index-range-and-meaning
+func (v *Visitor) calc(loc int) {
+ origVal := 171.0 - 5.2*math.Log(v.Coef.HalstVol.Val) - 0.23*float64(v.Coef.Cyc.Val) - 16.2*math.Log(float64(loc))
+ normVal := int(math.Max(0.0, origVal*100.0/171.0))
+ v.MaintIdx = normVal
+}
+
+// TODO: Move halstvol package
+func (v *Visitor) printHalstVol() {
+ sortedOpt := make([]string, len(v.Coef.HalstVol.Coef.Opt))
+ sortedOpd := make([]string, len(v.Coef.HalstVol.Coef.Opd))
+ optIndex := 0
+ opdIndex := 0
+ for key := range v.Coef.HalstVol.Coef.Opt {
+ sortedOpt[optIndex] = key
+ optIndex++
+ }
+ for key := range v.Coef.HalstVol.Coef.Opd {
+ sortedOpd[opdIndex] = key
+ opdIndex++
+ }
+ sort.Strings(sortedOpt)
+ sort.Strings(sortedOpd)
+ for _, val := range sortedOpt {
+ println("operators", val, v.Coef.HalstVol.Coef.Opt[val])
+ }
+ for _, val := range sortedOpd {
+ println("operands", val, v.Coef.HalstVol.Coef.Opd[val])
+ }
+}