Skip to content

Commit c8ad614

Browse files
committed
Provide a fix
1 parent 663afa4 commit c8ad614

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

analyzer.go

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ type Analyzer struct {
5252
template string
5353
}
5454

55-
func (a *Analyzer) Analyze(target *Target) Issue {
55+
func (a *Analyzer) Analyze(target *Target) (i Issue) {
5656
if a.template == "" {
5757
return NewIssue("Missed template for check")
5858
}
@@ -74,6 +74,16 @@ func (a *Analyzer) Analyze(target *Target) Issue {
7474
offset.Position += 3
7575
}
7676
}
77+
defer func() {
78+
if i.Message() == "" {
79+
return
80+
}
81+
fix, ok := a.generateFix(i, file, header)
82+
if !ok {
83+
return
84+
}
85+
i = NewIssueWithFix(i.Message(), i.Location(), fix)
86+
}()
7787
header = strings.TrimSpace(header)
7888
if header == "" {
7989
return NewIssue("Missed header for check")
@@ -144,3 +154,93 @@ func New(options ...Option) *Analyzer {
144154
}
145155
return a
146156
}
157+
158+
func (a *Analyzer) generateFix(i Issue, file *ast.File, header string) (Fix, bool) {
159+
var expect string
160+
t := NewReader(a.template)
161+
for !t.Done() {
162+
ch := t.Peek()
163+
if ch == '{' {
164+
f := a.values[a.readField(t)]
165+
if f == nil {
166+
return Fix{}, false
167+
}
168+
if f.Calculate(a.values) != nil {
169+
return Fix{}, false
170+
}
171+
expect += f.Get()
172+
continue
173+
}
174+
175+
expect += string(ch)
176+
t.Next()
177+
}
178+
179+
fix := Fix{Expected: strings.Split(expect, "\n")}
180+
if !(len(file.Comments) > 0 && file.Comments[0].Pos() < file.Package) {
181+
for i := range fix.Expected {
182+
fix.Expected[i] = "// " + fix.Expected[i]
183+
}
184+
return fix, true
185+
}
186+
187+
actual := file.Comments[0].List[0].Text
188+
if !strings.HasPrefix(actual, "/*") {
189+
for i := range fix.Expected {
190+
fix.Expected[i] = "// " + fix.Expected[i]
191+
}
192+
for _, c := range file.Comments[0].List {
193+
fix.Actual = append(fix.Actual, c.Text)
194+
}
195+
i = NewIssueWithFix(i.Message(), i.Location(), fix)
196+
return fix, true
197+
}
198+
199+
gets := func(i int, end bool) string {
200+
if i < 0 {
201+
return header
202+
}
203+
if end {
204+
return header[i+1:]
205+
}
206+
return header[:i]
207+
}
208+
start := strings.Index(actual, gets(strings.IndexByte(header, '\n'), false))
209+
if start < 0 {
210+
return Fix{}, false // Should be impossible
211+
}
212+
nl := strings.LastIndexByte(actual[:start], '\n')
213+
if nl >= 0 {
214+
fix.Actual = strings.Split(actual[:nl], "\n")
215+
fix.Expected = append(fix.Actual, fix.Expected...)
216+
actual = actual[nl+1:]
217+
start -= nl + 1
218+
}
219+
220+
prefix := actual[:start]
221+
if nl < 0 {
222+
fix.Expected[0] = prefix + fix.Expected[0]
223+
} else {
224+
n := len(fix.Actual)
225+
for i := range fix.Expected[n:] {
226+
fix.Expected[n+i] = prefix + fix.Expected[n+i]
227+
}
228+
}
229+
230+
last := gets(strings.LastIndexByte(header, '\n'), true)
231+
end := strings.Index(actual, last)
232+
if end < 0 {
233+
return Fix{}, false // Should be impossible
234+
}
235+
236+
trailing := actual[end+len(last):]
237+
if i := strings.IndexRune(trailing, '\n'); i < 0 {
238+
fix.Expected[len(fix.Expected)-1] += trailing
239+
} else {
240+
fix.Expected[len(fix.Expected)-1] += trailing[:i]
241+
fix.Expected = append(fix.Expected, strings.Split(trailing[i+1:], "\n")...)
242+
}
243+
244+
fix.Actual = append(fix.Actual, strings.Split(actual, "\n")...)
245+
return fix, true
246+
}

issue.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,18 @@ package goheader
1919
type Issue interface {
2020
Location() Location
2121
Message() string
22+
Fix() *Fix
2223
}
2324

2425
type issue struct {
2526
msg string
2627
location Location
28+
fix *Fix
29+
}
30+
31+
type Fix struct {
32+
Actual []string
33+
Expected []string
2734
}
2835

2936
func (i *issue) Location() Location {
@@ -34,13 +41,25 @@ func (i *issue) Message() string {
3441
return i.msg
3542
}
3643

44+
func (i *issue) Fix() *Fix {
45+
return i.fix
46+
}
47+
3748
func NewIssueWithLocation(msg string, location Location) Issue {
3849
return &issue{
3950
msg: msg,
4051
location: location,
4152
}
4253
}
4354

55+
func NewIssueWithFix(msg string, location Location, fix Fix) Issue {
56+
return &issue{
57+
msg: msg,
58+
location: location,
59+
fix: &fix,
60+
}
61+
}
62+
4463
func NewIssue(msg string) Issue {
4564
return &issue{
4665
msg: msg,

0 commit comments

Comments
 (0)