11package printers
22
33import (
4- "bytes"
54 "context"
65 "fmt"
7- "io/ioutil"
8- "time"
96
107 "github.com/fatih/color"
118 "github.com/golangci/golangci-lint/pkg/logutils"
129 "github.com/golangci/golangci-lint/pkg/result"
1310)
1411
15- type linesCache [][]byte
16- type filesCache map [string ]linesCache
17-
1812type Text struct {
1913 printIssuedLine bool
2014 useColors bool
2115 printLinterName bool
2216
23- cache filesCache
24- log logutils.Log
17+ log logutils.Log
2518}
2619
2720func NewText (printIssuedLine , useColors , printLinterName bool , log logutils.Log ) * Text {
2821 return & Text {
2922 printIssuedLine : printIssuedLine ,
3023 useColors : useColors ,
3124 printLinterName : printLinterName ,
32- cache : filesCache {},
3325 log : log ,
3426 }
3527}
@@ -43,56 +35,19 @@ func (p Text) SprintfColored(ca color.Attribute, format string, args ...interfac
4335 return c .Sprintf (format , args ... )
4436}
4537
46- func (p * Text ) getFileLinesForIssue (i * result.Issue ) (linesCache , error ) {
47- fc := p .cache [i .FilePath ()]
48- if fc != nil {
49- return fc , nil
50- }
51-
52- // TODO: make more optimal algorithm: don't load all files into memory
53- fileBytes , err := ioutil .ReadFile (i .FilePath ())
54- if err != nil {
55- return nil , fmt .Errorf ("can't read file %s for printing issued line: %s" , i .FilePath (), err )
56- }
57- lines := bytes .Split (fileBytes , []byte ("\n " )) // TODO: what about \r\n?
58- fc = lines
59- p .cache [i .FilePath ()] = fc
60- return fc , nil
61- }
62-
63- func (p * Text ) Print (ctx context.Context , issues <- chan result.Issue ) (bool , error ) {
64- var issuedLineExtractingDuration time.Duration
65- defer func () {
66- p .log .Infof ("Extracting issued lines took %s" , issuedLineExtractingDuration )
67- }()
68-
69- issuesN := 0
38+ func (p * Text ) Print (ctx context.Context , issues <- chan result.Issue ) error {
7039 for i := range issues {
71- issuesN ++
7240 p .printIssue (& i )
7341
7442 if ! p .printIssuedLine {
7543 continue
7644 }
7745
78- startedAt := time .Now ()
79- lines , err := p .getFileLinesForIssue (& i )
80- if err != nil {
81- return false , err
82- }
83- issuedLineExtractingDuration += time .Since (startedAt )
84-
85- p .printIssuedLines (& i , lines )
86- if i .Line ()- 1 < len (lines ) {
87- p .printUnderLinePointer (& i , string (lines [i .Line ()- 1 ]))
88- }
89- }
90-
91- if issuesN != 0 {
92- p .log .Infof ("Found %d issues" , issuesN )
46+ p .printSourceCode (& i )
47+ p .printUnderLinePointer (& i )
9348 }
9449
95- return issuesN != 0 , nil
50+ return nil
9651}
9752
9853func (p Text ) printIssue (i * result.Issue ) {
@@ -107,32 +62,19 @@ func (p Text) printIssue(i *result.Issue) {
10762 fmt .Fprintf (logutils .StdOut , "%s: %s\n " , pos , text )
10863}
10964
110- func (p Text ) printIssuedLines (i * result.Issue , lines linesCache ) {
111- lineRange := i .GetLineRange ()
112- var lineStr string
113- for line := lineRange .From ; line <= lineRange .To ; line ++ {
114- if line == 0 { // some linters, e.g. gas can do it: it really means first line
115- line = 1
116- }
117-
118- zeroIndexedLine := line - 1
119- if zeroIndexedLine >= len (lines ) {
120- p .log .Warnf ("No line %d in file %s" , line , i .FilePath ())
121- break
122- }
123-
124- lineStr = string (bytes .Trim (lines [zeroIndexedLine ], "\r " ))
125- fmt .Fprintln (logutils .StdOut , lineStr )
65+ func (p Text ) printSourceCode (i * result.Issue ) {
66+ for _ , line := range i .SourceLines {
67+ fmt .Fprintln (logutils .StdOut , line )
12668 }
12769}
12870
129- func (p Text ) printUnderLinePointer (i * result.Issue , line string ) {
130- lineRange := i .GetLineRange ()
131- if lineRange .From != lineRange .To || i .Pos .Column == 0 {
71+ func (p Text ) printUnderLinePointer (i * result.Issue ) {
72+ if len (i .SourceLines ) != 1 || i .Pos .Column == 0 {
13273 return
13374 }
13475
13576 col0 := i .Pos .Column - 1
77+ line := i .SourceLines [0 ]
13678 prefixRunes := make ([]rune , 0 , len (line ))
13779 for j := 0 ; j < len (line ) && j < col0 ; j ++ {
13880 if line [j ] == '\t' {
0 commit comments