Create Your First Linter

Manuel Doncel Martos -

Powered by reveal.js

QR Code Slides

Linter

Automatically analyze source code for potential errors, stylistic issues, and violations of coding conventions

About me


            var Me = Developer{
                Name: "Manuel Doncel Martos",
                Skills: [][]string{
                  {"☕Java", "Spring Boot"},
                  {"🦫Go", "🐍Python"},
                  {"Kubernetes", "Docker"},
                },
                Interests: []string {
                  "Open Source",
                  "Domain Driven Design",
                  "⚽Football",
                },
            }
            
QR Code GitHub manuelarte

Agenda

golangci-lint

Golangci-lint is a fast linters runner for Go.

  • Widely used.
  • More than 100 linters.
  • Run linters.
  • Run formatters.

                            @startuml
                            skinparam backgroundColor transparent
                            skinparam monochrome reverse
                            !option handwritten true

                            revive - [golangci-lint]
                            gofmt - [golangci-lint]
                            gofumpt - [golangci-lint]
                            gci - [golangci-lint]
                            ... - [golangci-lint]
                            funcorder -- [golangci-lint]
                            embeddedstructfieldcheck -- [golangci-lint]

                            @enduml
                            

Example configurations


            version: 2
            

Others:

Tools Analyzer

Package golang.org/x/tools

  • Token
  • Analyzer
  • Pass
  • Diagnosis

AST Parser


              @startwbs

              skinparam backgroundColor transparent
              skinparam monochrome reverse
              !option handwritten true

              * ast.File
              ** ast.GenDecl
              *** ast.ImportSpec
              **** ast.BasicLit
              ** ast.GenDecl
              *** ast.ValueSpec
              **** ast.Ident
              **** ast.BasicLit
              ** ast.GenDecl
              *** ast.TypeSpec
              *** ast.StructType
              **** ast.FieldList
              ***** ast.Field
              ***** ast.Field
              ** ast.FuncDecl
              *** ast.FuncType
              *** ast.FieldList
              **** ast.Field
              **** ast.Field
              ** ...

              @endwbs
              

File to test: here

Create your first linter

Prefix unexported globals with '_' .

❌ Bad

                const myConstant = "myConstant"
                const errNotFound = "not found"
              
✅ Good

                const _myConstant = "myConstant"
                const errNotFound = "not found"
              
  • Identify
  • Suggest fix

Let's

go

🧐 My linters

FuncOrder

❌ Bad

                        // ❌ constructor before
                        // struct declaration
                        func NewMyStruct() *MyStruct {
                            return &MyStruct{}
                        }

                        type MyStruct struct {
                            Name string
                        }

                        // ❌ unexported method
                        // placed before exported method
                        func (m MyStruct) lenName() int {
                            return len(m.Name)
                        }

                        func (m MyStruct) GetName() string {
                            return m.Name
                        }

                        ...
                        type Client struct {
                          version int
                          http.Client
                        }
                 
✅ Good

                        type MyStruct struct {
                            Name string
                        }

                        // ✅ constructor after
                        // struct declaration and
                        // before methods
                        func NewMyStruct() *MyStruct {
                            return &MyStruct{}
                        }

                        // ✅ exported methods before
                        // unexported methods
                        func (m MyStruct) GetName() string {
                            return m.Name
                        }

                        func (m MyStruct) lenName() int {
                            return len(m.Name)
                        }

                        ...
                  

EmbeddedStructFieldCheck

❌ Bad

                        type Client struct {
                          version int
                          http.Client
                        }
                 
✅ Good

                        type Client struct {
                          http.Client

                          version int
                        }
                  

Create custom plugin

More info: Module Plugin

Example: Custom Plugin

Let's

go

Q/A

form