Skip to content

Commit

Permalink
feat: remove golangci-lint mode (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez authored Dec 17, 2024
1 parent e22f14a commit 3d7a6d9
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 115 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/go.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: stable

- name: Build
run: go build -v ./...

- name: Test
run: go test -v ./...

- name: Run
run: go run ./cmd/whitespace/ ./...
149 changes: 39 additions & 110 deletions whitespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,8 @@ import (
"golang.org/x/tools/go/analysis"
)

// MessageType describes what should happen to fix the warning.
type MessageType uint8

// List of MessageTypes.
const (
MessageTypeRemove MessageType = iota + 1
MessageTypeAdd
)

// RunningMode describes the mode the linter is run in. This can be either
// native or golangci-lint.
type RunningMode uint8

const (
RunningModeNative RunningMode = iota
RunningModeGolangCI
)

// Message contains a message and diagnostic information.
type Message struct {
// Diagnostic is what position the diagnostic should be put at. This isn't
// always the same as the fix start, f.ex. when we fix trailing newlines we
// put the diagnostic at the right bracket but we fix between the end of the
// last statement and the bracket.
Diagnostic token.Pos

// FixStart is the span start of the fix.
FixStart token.Pos

// FixEnd is the span end of the fix.
FixEnd token.Pos

// LineNumbers represent the actual line numbers in the file. This is set
// when finding the diagnostic to make it easier to suggest fixes in
// golangci-lint.
LineNumbers []int

// MessageType represents the type of message it is.
MessageType MessageType

// Message is the diagnostic to show.
Message string
}

// Settings contains settings for edge-cases.
type Settings struct {
Mode RunningMode
MultiIf bool
MultiFunc bool
}
Expand Down Expand Up @@ -86,47 +41,24 @@ func flags(settings *Settings) flag.FlagSet {
return *flags
}

func Run(pass *analysis.Pass, settings *Settings) []Message {
messages := []Message{}

func Run(pass *analysis.Pass, settings *Settings) {
for _, file := range pass.Files {
filename := pass.Fset.Position(file.Pos()).Filename

if !strings.HasSuffix(filename, ".go") {
continue
}

fileMessages := runFile(file, pass.Fset, *settings)

if settings.Mode == RunningModeGolangCI {
messages = append(messages, fileMessages...)
continue
}

for _, message := range fileMessages {
pass.Report(analysis.Diagnostic{
Pos: message.Diagnostic,
Category: "whitespace",
Message: message.Message,
SuggestedFixes: []analysis.SuggestedFix{
{
TextEdits: []analysis.TextEdit{
{
Pos: message.FixStart,
End: message.FixEnd,
NewText: []byte("\n"),
},
},
},
},
})
pass.Report(message)
}
}

return messages
}

func runFile(file *ast.File, fset *token.FileSet, settings Settings) []Message {
var messages []Message
func runFile(file *ast.File, fset *token.FileSet, settings Settings) []analysis.Diagnostic {
var messages []analysis.Diagnostic

for _, f := range file.Decls {
decl, ok := f.(*ast.FuncDecl)
Expand All @@ -146,7 +78,7 @@ func runFile(file *ast.File, fset *token.FileSet, settings Settings) []Message {
type visitor struct {
comments []*ast.CommentGroup
fset *token.FileSet
messages []Message
messages []analysis.Diagnostic
wantNewline map[*ast.BlockStmt]bool
settings Settings
}
Expand Down Expand Up @@ -180,13 +112,16 @@ func (v *visitor) Visit(node ast.Node) ast.Visitor {
startMsg := checkStart(v.fset, opening, first)

if wantNewline && startMsg == nil && len(stmt.List) >= 1 {
v.messages = append(v.messages, Message{
Diagnostic: opening,
FixStart: stmt.List[0].Pos(),
FixEnd: stmt.List[0].Pos(),
LineNumbers: []int{v.fset.PositionFor(stmt.List[0].Pos(), false).Line},
MessageType: MessageTypeAdd,
Message: "multi-line statement should be followed by a newline",
v.messages = append(v.messages, analysis.Diagnostic{
Pos: opening,
Message: "multi-line statement should be followed by a newline",
SuggestedFixes: []analysis.SuggestedFix{{
TextEdits: []analysis.TextEdit{{
Pos: stmt.List[0].Pos(),
End: stmt.List[0].Pos(),
NewText: []byte("\n"),
}},
}},
})
} else if !wantNewline && startMsg != nil {
v.messages = append(v.messages, *startMsg)
Expand All @@ -209,7 +144,7 @@ func checkMultiLine(v *visitor, body *ast.BlockStmt, stmtStart ast.Node) {
}

func posLine(fset *token.FileSet, pos token.Pos) int {
return fset.PositionFor(pos, false).Line
return fset.Position(pos).Line
}

func firstAndLast(comments []*ast.CommentGroup, fset *token.FileSet, stmt *ast.BlockStmt) (token.Pos, ast.Node, ast.Node) {
Expand Down Expand Up @@ -256,52 +191,46 @@ func firstAndLast(comments []*ast.CommentGroup, fset *token.FileSet, stmt *ast.B
return openingPos, first, last
}

func checkStart(fset *token.FileSet, start token.Pos, first ast.Node) *Message {
func checkStart(fset *token.FileSet, start token.Pos, first ast.Node) *analysis.Diagnostic {
if first == nil {
return nil
}

if posLine(fset, start)+1 < posLine(fset, first.Pos()) {
return &Message{
Diagnostic: start,
FixStart: start,
FixEnd: first.Pos(),
LineNumbers: linesBetween(fset, start, first.Pos()),
MessageType: MessageTypeRemove,
Message: "unnecessary leading newline",
return &analysis.Diagnostic{
Pos: start,
Message: "unnecessary leading newline",
SuggestedFixes: []analysis.SuggestedFix{{
TextEdits: []analysis.TextEdit{{
Pos: start,
End: first.Pos(),
NewText: []byte("\n"),
}},
}},
}
}

return nil
}

func checkEnd(fset *token.FileSet, end token.Pos, last ast.Node) *Message {
func checkEnd(fset *token.FileSet, end token.Pos, last ast.Node) *analysis.Diagnostic {
if last == nil {
return nil
}

if posLine(fset, end)-1 > posLine(fset, last.End()) {
return &Message{
Diagnostic: end,
FixStart: last.End(),
FixEnd: end,
LineNumbers: linesBetween(fset, last.End(), end),
MessageType: MessageTypeRemove,
Message: "unnecessary trailing newline",
return &analysis.Diagnostic{
Pos: end,
Message: "unnecessary trailing newline",
SuggestedFixes: []analysis.SuggestedFix{{
TextEdits: []analysis.TextEdit{{
Pos: last.End(),
End: end,
NewText: []byte("\n"),
}},
}},
}
}

return nil
}

func linesBetween(fset *token.FileSet, a, b token.Pos) []int {
lines := []int{}
aPosition := fset.PositionFor(a, false)
bPosition := fset.PositionFor(b, false)

for i := aPosition.Line + 1; i < bPosition.Line; i++ {
lines = append(lines, i)
}

return lines
}
2 changes: 0 additions & 2 deletions whitespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
func TestWantMultiline(t *testing.T) {
testdata := analysistest.TestData()
analyzer := NewAnalyzer(&Settings{
Mode: RunningModeNative,
MultiIf: true,
MultiFunc: true,
})
Expand All @@ -20,7 +19,6 @@ func TestWantMultiline(t *testing.T) {
func TestNoMultiline(t *testing.T) {
testdata := analysistest.TestData()
analyzer := NewAnalyzer(&Settings{
Mode: RunningModeNative,
MultiIf: false,
MultiFunc: false,
})
Expand Down

0 comments on commit 3d7a6d9

Please sign in to comment.