cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.81.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/parser/read.go

186lines · 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))
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 FirstColumn: comment.Offset + 1,
105 LastColumn: len(r.buf) - 1,
106 Kind: diags.Issue,
107 })
108 case comments.IgnoreLineType:
109 skip = skipCurrentLine
110 found = true
111 case comments.IgnoreBeginType:
112 skip = skipBegin
113 found = true
114 case comments.IgnoreEndType:
115 skip = skipEnd
116 found = true
117 case comments.IgnoreNextLineType:
118 skip = skipNextLine
119 found = true
120 case comments.FileOwnerType:
121 r.comments = append(r.comments, comment)
122 case comments.RuleOwnerType:
123 // pass
124 case comments.FileDisableType:
125 r.comments = append(r.comments, comment)
126 case comments.DisableType:
127 // pass
128 case comments.FileSnoozeType:
129 r.comments = append(r.comments, comment)
130 case comments.SnoozeType:
131 // pass
132 case comments.RuleSetType:
133 // pass
134 case comments.InvalidComment:
135 r.comments = append(r.comments, comment)
136 }
137 }
138 switch {
139 case found:
140 switch skip { // nolint: exhaustive
141 case skipFile:
142 r.emptyCurrentLine(lineComments)
143 r.skipNext = true
144 r.autoReset = false
145 r.skipAll = true
146 case skipCurrentLine:
147 r.emptyCurrentLine(lineComments)
148 if !r.inBegin {
149 r.skipNext = false
150 r.autoReset = true
151 }
152 case skipNextLine:
153 r.skipNext = true
154 r.autoReset = true
155 case skipBegin:
156 r.skipNext = true
157 r.autoReset = false
158 r.inBegin = true
159 case skipEnd:
160 r.skipNext = false
161 r.autoReset = true
162 r.inBegin = false
163 }
164 case r.skipNext:
165 r.emptyCurrentLine(lineComments)
166 if r.autoReset {
167 r.skipNext = false
168 }
169 }
170}
171
172func (r *ContentReader) emptyCurrentLine(comments []comments.Comment) {
173 offset := len(r.buf)
174 for _, c := range comments {
175 offset = c.Offset
176 break
177 }
178 for i := range r.buf {
179 if r.buf[i] == '\n' || r.buf[i] == '\r' {
180 continue
181 }
182 if i < offset || r.inBegin {
183 r.buf[i] = ' '
184 }
185 }
186}
187