www.github.com/golangci/golangci-lint.git@v1.10.1/pkg/golinters/typecheck.go (about)

     1  package golinters
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"go/token"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/golangci/golangci-lint/pkg/lint/linter"
    12  	"github.com/golangci/golangci-lint/pkg/result"
    13  )
    14  
    15  type TypeCheck struct{}
    16  
    17  func (TypeCheck) Name() string {
    18  	return "typecheck"
    19  }
    20  
    21  func (TypeCheck) Desc() string {
    22  	return "Like the front-end of a Go compiler, parses and type-checks Go code"
    23  }
    24  
    25  func (lint TypeCheck) parseError(srcErr error) (*result.Issue, error) {
    26  	// TODO: cast srcErr to types.Error and just use it
    27  
    28  	// file:line(<optional>:colon): message
    29  	parts := strings.Split(srcErr.Error(), ":")
    30  	if len(parts) < 3 {
    31  		return nil, errors.New("too few colons")
    32  	}
    33  
    34  	file := parts[0]
    35  	line, err := strconv.Atoi(parts[1])
    36  	if err != nil {
    37  		return nil, fmt.Errorf("can't parse line number %q: %s", parts[1], err)
    38  	}
    39  
    40  	var column int
    41  	var message string
    42  	if len(parts) == 3 { // no column
    43  		message = parts[2]
    44  	} else {
    45  		column, err = strconv.Atoi(parts[2])
    46  		if err == nil { // column was parsed
    47  			message = strings.Join(parts[3:], ":")
    48  		} else {
    49  			message = strings.Join(parts[2:], ":")
    50  		}
    51  	}
    52  
    53  	message = strings.TrimSpace(message)
    54  	if message == "" {
    55  		return nil, fmt.Errorf("empty message")
    56  	}
    57  
    58  	return &result.Issue{
    59  		Pos: token.Position{
    60  			Filename: file,
    61  			Line:     line,
    62  			Column:   column,
    63  		},
    64  		Text:       markIdentifiers(message),
    65  		FromLinter: lint.Name(),
    66  	}, nil
    67  }
    68  
    69  func (lint TypeCheck) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
    70  	var res []result.Issue
    71  	for _, pkg := range lintCtx.NotCompilingPackages {
    72  		for _, err := range pkg.Errors {
    73  			i, perr := lint.parseError(err)
    74  			if perr != nil {
    75  				lintCtx.Log.Warnf("Can't parse type error %s: %s", err, perr)
    76  			} else {
    77  				res = append(res, *i)
    78  			}
    79  		}
    80  	}
    81  
    82  	return res, nil
    83  }