cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.84.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/parser/read.go

187lines · modecode

1package parser
2
3import (
4 "bufio"
5 "io"
6 "strings"
7
8 "github.com/cloudflare/pint/internal/comments"
9 "github.com/cloudflare/pint/internal/diags"
10)
11
12type skipMode uint8
13
14const (
15 skipNone skipMode = iota
16 skipNextLine
17 skipBegin
18 skipEnd
19 skipCurrentLine
20 skipFile
21)
22
23func newContentReader(r io.Reader) *ContentReader {
24 return &ContentReader{
25 src: bufio.NewReader(r),
26 buf: nil,
27 lines: make([]string, 0, 100),
28 comments: nil,
29 diagnostics: nil,
30 lineno: 0,
31 skipAll: false,
32 skipNext: false,
33 autoReset: false,
34 inBegin: false,
35 }
36}
37
38type ContentReader struct {
39 src *bufio.Reader
40 buf []byte
41 comments []comments.Comment
42 diagnostics []diags.Diagnostic
43 lines []string
44 lineno int
45
46 skipAll bool
47 skipNext bool
48 autoReset bool
49 inBegin bool
50}
51
52func (r *ContentReader) Read(b []byte) (got int, err error) {
53 for got < cap(b) && err == nil {
54 if len(r.buf) == 0 {
55 err = r.readNextLine()
56 }
57 n := copy(b[got:], r.buf)
58 r.buf = r.buf[n:]
59 got += n
60 }
61 if err != nil && len(r.buf) > 0 {
62 err = nil
63 }
64 return got, err
65}
66
67func (r *ContentReader) readNextLine() (err error) {
68 r.buf, err = r.src.ReadBytes('\n')
69 if len(r.buf) == 0 {
70 return err
71 }
72
73 r.lineno++
74 r.parseComments()
75 r.lines = append(r.lines, strings.TrimRight(string(r.buf), "\r\n"))
76 return err
77}
78
79func (r *ContentReader) parseComments() {
80 lineComments := comments.Parse(r.lineno, string(r.buf), 0)
81
82 if r.skipAll {
83 r.emptyCurrentLine(lineComments)
84 return
85 }
86
87 var found bool
88 var skip skipMode
89 for _, comment := range lineComments {
90 // nolint:exhaustive
91 switch comment.Type {
92 case comments.IgnoreFileType:
93 skip = skipFile
94 found = true
95 r.diagnostics = append(r.diagnostics, diags.Diagnostic{
96 Message: "This file was excluded from pint checks.",
97 Pos: diags.PositionRanges{
98 {
99 Line: r.lineno,
100 FirstColumn: comment.Offset + 1,
101 LastColumn: len(r.buf) - 1,
102 },
103 },
104 Expr: nil,
105 FirstColumn: comment.Offset + 1,
106 LastColumn: len(r.buf) - 1,
107 Kind: diags.Issue,
108 })
109 case comments.IgnoreLineType:
110 skip = skipCurrentLine
111 found = true
112 case comments.IgnoreBeginType:
113 skip = skipBegin
114 found = true
115 case comments.IgnoreEndType:
116 skip = skipEnd
117 found = true
118 case comments.IgnoreNextLineType:
119 skip = skipNextLine
120 found = true
121 case comments.FileOwnerType:
122 r.comments = append(r.comments, comment)
123 case comments.RuleOwnerType:
124 // pass
125 case comments.FileDisableType:
126 r.comments = append(r.comments, comment)
127 case comments.DisableType:
128 // pass
129 case comments.FileSnoozeType:
130 r.comments = append(r.comments, comment)
131 case comments.SnoozeType:
132 // pass
133 case comments.RuleSetType:
134 // pass
135 case comments.InvalidComment:
136 r.comments = append(r.comments, comment)
137 }
138 }
139 switch {
140 case found:
141 switch skip { // nolint: exhaustive
142 case skipFile:
143 r.emptyCurrentLine(lineComments)
144 r.skipNext = true
145 r.autoReset = false
146 r.skipAll = true
147 case skipCurrentLine:
148 r.emptyCurrentLine(lineComments)
149 if !r.inBegin {
150 r.skipNext = false
151 r.autoReset = true
152 }
153 case skipNextLine:
154 r.skipNext = true
155 r.autoReset = true
156 case skipBegin:
157 r.skipNext = true
158 r.autoReset = false
159 r.inBegin = true
160 case skipEnd:
161 r.skipNext = false
162 r.autoReset = true
163 r.inBegin = false
164 }
165 case r.skipNext:
166 r.emptyCurrentLine(lineComments)
167 if r.autoReset {
168 r.skipNext = false
169 }
170 }
171}
172
173func (r *ContentReader) emptyCurrentLine(comments []comments.Comment) {
174 offset := len(r.buf)
175 for _, c := range comments {
176 offset = c.Offset
177 break
178 }
179 for i := range r.buf {
180 if r.buf[i] == '\n' || r.buf[i] == '\r' {
181 continue
182 }
183 if i < offset || r.inBegin {
184 r.buf[i] = ' '
185 }
186 }
187}
188