diff --git a/tagalign.go b/tagalign.go index c998510..08cd06e 100644 --- a/tagalign.go +++ b/tagalign.go @@ -29,6 +29,10 @@ const ( StrictStyle ) +const ( + errTagValueSyntax = "bad syntax for struct tag value" +) + func NewAnalyzer(options ...Option) *analysis.Analyzer { return &analysis.Analyzer{ Name: "tagalign", @@ -207,19 +211,25 @@ func (w *Helper) Process(pass *analysis.Pass) { //nolint:gocognit } uniqueKeys = append(uniqueKeys, k) } + mark := make(map[int]struct{}) for i, field := range fields { - offsets[i] = pass.Fset.Position(field.Tag.Pos()).Column + column := pass.Fset.Position(field.Tag.Pos()).Column - 1 tag, err := strconv.Unquote(field.Tag.Value) if err != nil { - break + mark[i] = struct{}{} + w.report(pass, field, column, errTagValueSyntax, field.Tag.Value) + continue } tags, err := structtag.Parse(tag) if err != nil { - break + mark[i] = struct{}{} + w.report(pass, field, column, err.Error(), field.Tag.Value) + continue } + offsets = append(offsets, column) maxTagNum = max(maxTagNum, tags.Len()) if w.sort { @@ -236,6 +246,17 @@ func (w *Helper) Process(pass *analysis.Pass) { //nolint:gocognit tagsGroup = append(tagsGroup, tags.Tags()) } + offset := 0 + for i := range fields { + if _, exist := mark[i]; exist { + continue + } + + fields[offset] = fields[i] + offset++ + } + fields = fields[:offset] + if w.sort && StrictStyle == w.style { sortAllKeys(w.fixedTagOrder, uniqueKeys) maxTagNum = len(uniqueKeys) @@ -325,19 +346,22 @@ func (w *Helper) Process(pass *analysis.Pass) { //nolint:gocognit msg := "tag is not aligned, should be: " + unquoteTag - w.report(pass, field, offsets[i]-1, msg, newTagValue) + w.report(pass, field, offsets[i], msg, newTagValue) } } // process single fields for _, field := range w.singleFields { + column := pass.Fset.Position(field.Tag.Pos()).Column - 1 tag, err := strconv.Unquote(field.Tag.Value) if err != nil { + w.report(pass, field, column, errTagValueSyntax, field.Tag.Value) continue } tags, err := structtag.Parse(tag) if err != nil { + w.report(pass, field, column, err.Error(), field.Tag.Value) continue } originalTags := append([]*structtag.Tag(nil), tags.Tags()...) @@ -353,7 +377,7 @@ func (w *Helper) Process(pass *analysis.Pass) { //nolint:gocognit msg := "tag is not aligned , should be: " + tags.String() - w.report(pass, field, pass.Fset.Position(field.Tag.Pos()).Column-1, msg, newTagValue) + w.report(pass, field, column, msg, newTagValue) } } diff --git a/tagalign_test.go b/tagalign_test.go index abf6945..cc84767 100644 --- a/tagalign_test.go +++ b/tagalign_test.go @@ -39,6 +39,7 @@ func Test_alignAndSortWithOrder(t *testing.T) { assert.NoError(t, err) analysistest.Run(t, sort, a) } + func TestSprintf(t *testing.T) { format := alignFormat(20) assert.Equal(t, "%-20s", format) @@ -72,3 +73,11 @@ func Test_alignSingleField(t *testing.T) { assert.NoError(t, err) analysistest.Run(t, unsort, a) } + +func Test_issues6(t *testing.T) { + // only align + a := NewAnalyzer() + unsort, err := filepath.Abs("testdata/issues6") + assert.NoError(t, err) + analysistest.Run(t, unsort, a) +} diff --git a/testdata/issues6/example.go b/testdata/issues6/example.go new file mode 100644 index 0000000..0486daa --- /dev/null +++ b/testdata/issues6/example.go @@ -0,0 +1,8 @@ +package issues6 + +type FooBar struct { + Foo int `json: "foo" validate:"required"` // want `bad syntax for struct tag value` + Bar string `json:bar` // want `bad syntax for struct tag value` + FooFoo int8 `json:"foo_foo" validate:"required"` + BarBar int `json:"bar_bar" validate:"required"` +}