github.com/shulhan/golangci-lint@v1.10.1/pkg/printers/text.go (about)

     1  package printers
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/fatih/color"
     8  	"github.com/golangci/golangci-lint/pkg/logutils"
     9  	"github.com/golangci/golangci-lint/pkg/result"
    10  )
    11  
    12  type Text struct {
    13  	printIssuedLine bool
    14  	useColors       bool
    15  	printLinterName bool
    16  
    17  	log logutils.Log
    18  }
    19  
    20  func NewText(printIssuedLine, useColors, printLinterName bool, log logutils.Log) *Text {
    21  	return &Text{
    22  		printIssuedLine: printIssuedLine,
    23  		useColors:       useColors,
    24  		printLinterName: printLinterName,
    25  		log:             log,
    26  	}
    27  }
    28  
    29  func (p Text) SprintfColored(ca color.Attribute, format string, args ...interface{}) string {
    30  	if !p.useColors {
    31  		return fmt.Sprintf(format, args...)
    32  	}
    33  
    34  	c := color.New(ca)
    35  	return c.Sprintf(format, args...)
    36  }
    37  
    38  func (p *Text) Print(ctx context.Context, issues <-chan result.Issue) error {
    39  	for i := range issues {
    40  		p.printIssue(&i)
    41  
    42  		if !p.printIssuedLine {
    43  			continue
    44  		}
    45  
    46  		p.printSourceCode(&i)
    47  		p.printUnderLinePointer(&i)
    48  	}
    49  
    50  	return nil
    51  }
    52  
    53  func (p Text) printIssue(i *result.Issue) {
    54  	text := p.SprintfColored(color.FgRed, "%s", i.Text)
    55  	if p.printLinterName {
    56  		text += fmt.Sprintf(" (%s)", i.FromLinter)
    57  	}
    58  	pos := p.SprintfColored(color.Bold, "%s:%d", i.FilePath(), i.Line())
    59  	if i.Pos.Column != 0 {
    60  		pos += fmt.Sprintf(":%d", i.Pos.Column)
    61  	}
    62  	fmt.Fprintf(logutils.StdOut, "%s: %s\n", pos, text)
    63  }
    64  
    65  func (p Text) printSourceCode(i *result.Issue) {
    66  	for _, line := range i.SourceLines {
    67  		fmt.Fprintln(logutils.StdOut, line)
    68  	}
    69  }
    70  
    71  func (p Text) printUnderLinePointer(i *result.Issue) {
    72  	// if column == 0 it means column is unknown (e.g. for gas)
    73  	if len(i.SourceLines) != 1 || i.Pos.Column == 0 {
    74  		return
    75  	}
    76  
    77  	col0 := i.Pos.Column - 1
    78  	line := i.SourceLines[0]
    79  	prefixRunes := make([]rune, 0, len(line))
    80  	for j := 0; j < len(line) && j < col0; j++ {
    81  		if line[j] == '\t' {
    82  			prefixRunes = append(prefixRunes, '\t')
    83  		} else {
    84  			prefixRunes = append(prefixRunes, ' ')
    85  		}
    86  	}
    87  
    88  	fmt.Fprintf(logutils.StdOut, "%s%s\n", string(prefixRunes), p.SprintfColored(color.FgYellow, "^"))
    89  }