cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.73.7

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/parser/read.go

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