codeclimate-community/codeclimate-golint

View on GitHub
codeclimate-golint.go

Summary

Maintainability
A
0 mins
Test Coverage
package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "strconv"
    "strings"

    "github.com/codeclimate/cc-engine-go/engine"
    "golang.org/x/lint"
)

const defaultMinConfidence = 0.8

func main() {
    rootPath := "/code/"

    config, err := engine.LoadConfig()
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error loading config: %s", err)
        os.Exit(1)
    }

    analysisFiles, err := engine.GoFileWalk(rootPath, engine.IncludePaths(rootPath, config))
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error initializing: %s", err)
        os.Exit(1)
    }

    minConfidence := getMinConfidence(config)

    for _, path := range analysisFiles {
        relativePath := strings.SplitAfter(path, rootPath)[1]

        lintFile(path, relativePath, minConfidence)
    }
}

func lintFile(fullPath string, relativePath string, minConfidence float64) {
    linter := new(lint.Linter)

    code, err := ioutil.ReadFile(fullPath)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Could not read file: %v\n", fullPath)
        fmt.Fprintf(os.Stderr, "Error %v\n", err)
        os.Exit(1)
    }

    problems, err := linter.Lint(fullPath, code)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Could not lint file: %v\n", fullPath)
        fmt.Fprintf(os.Stderr, "Error %v\n", err)
        os.Exit(1)
    }

    for _, problem := range problems {
        if problem.Confidence < minConfidence {
            continue
        }

        issue := &engine.Issue{
            Type:              "issue",
            Check:             codeClimateCheckName(&problem),
            Description:       (&problem).Text,
            RemediationPoints: 50000,
            Categories:        []string{"Style"},
            Location:          codeClimateLocation(&problem, relativePath),
        }
        engine.PrintIssue(issue)
    }
}

func codeClimateCheckName(l *lint.Problem) string {
    return "GoLint/" + strings.Title(l.Category) + "/" + codeClimateIssueName(l)
}

func codeClimateIssueName(l *lint.Problem) string {
    splitURL := strings.Split(l.Link, "#")
    kebabLink := splitURL[len(splitURL)-1]
    splitLink := strings.Split(kebabLink, "-")
    for i, link := range splitLink {
        splitLink[i] = strings.Title(link)
    }
    camelLink := strings.Join(splitLink, "")
    return camelLink
}

func codeClimateLocation(l *lint.Problem, relativePath string) *engine.Location {
    position := l.Position

    return &engine.Location{
        Path: relativePath,
        Lines: &engine.LinesOnlyPosition{
            Begin: position.Line,
            End:   position.Line,
        },
    }
}

func getMinConfidence(config engine.Config) float64 {
    if subConfig, ok := config["config"].(map[string]interface{}); ok {
        if minConfidence, ok := subConfig["min_confidence"].(string); ok {
            val, err := strconv.ParseFloat(minConfidence, 64)
            if err == nil {
                return val
            }
        }
    }
    return defaultMinConfidence
}