protogetter

package module
v0.3.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 19, 2024 License: MIT Imports: 14 Imported by: 2

README

Protogetter

Welcome to the Protogetter project!

Overview

Protogetter is a linter developed specifically for Go programmers working with nested protobuf types.
It's designed to aid developers in preventing invalid memory address or nil pointer dereference errors arising from direct access of nested protobuf fields.

When working with protobuf, it's quite common to have complex structures where a message field is contained within another message, which itself can be part of another message, and so on. If these fields are accessed directly and some field in the call chain will not be initialized, it can result in application panic.

Protogetter addresses this issue by suggesting use of getter methods for field access.

How does it work?

Protogetter analyzes your Go code and helps detect direct protobuf field accesses that could give rise to panic.
The linter suggests using getters:

m.GetFoo().GetBar().GetBaz()

instead of direct field access:

m.Foo.Bar.Baz

And you will then only need to perform a nil check after the final call:

if m.GetFoo().GetBar().GetBaz() != nil {
    // Do something with m.GetFoo().GetBar().GetBaz()
}

instead of:

if m.Foo != nil {
    if m.Foo.Bar != nil {
        if m.Foo.Bar.Baz != nil {
            // Do something with m.Foo.Bar.Baz
        }
    }
}

or use zero values:

// If one of the methods returns `nil` we will receive 0 instead of panic.
v := m.GetFoo().GetBar().GetBaz().GetInt() 

instead of panic:

// If at least one structure in the chains is not initialized, we will get a panic. 
v := m.Foo.Bar.Baz.Int

which simplifies the code and makes it more reliable.

Installation

go install github.com/ghostiam/protogetter/cmd/protogetter@latest

Usage

To run the linter:

protogetter ./...

Or to apply suggested fixes directly:

protogetter --fix ./...

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewAnalyzer

func NewAnalyzer(cfg *Config) *analysis.Analyzer

Types

type Config added in v0.3.0

type Config struct {
	Mode                    Mode // Zero value is StandaloneMode.
	SkipGeneratedBy         []string
	SkipFiles               []string
	SkipAnyGenerated        bool
	ReplaceFirstArgInAppend bool
}

type InlineFix

type InlineFix struct {
	StartCol  int // zero-based
	Length    int
	NewString string
}

type Issue

type Issue struct {
	Pos       token.Position
	Message   string
	InlineFix InlineFix
}

Issue is used to integrate with golangci-lint's inline auto fix.

func Run

func Run(pass *analysis.Pass, cfg *Config) ([]Issue, error)

type Mode

type Mode int
const (
	StandaloneMode Mode = iota
	GolangciLintMode
)

type PosFilter

type PosFilter struct {
	// contains filtered or unexported fields
}

func NewPosFilter

func NewPosFilter() *PosFilter

func (*PosFilter) AddAlreadyReplaced

func (f *PosFilter) AddAlreadyReplaced(fset *token.FileSet, pos, end token.Pos)

func (*PosFilter) AddPos

func (f *PosFilter) AddPos(pos token.Pos)

func (*PosFilter) IsAlreadyReplaced

func (f *PosFilter) IsAlreadyReplaced(fset *token.FileSet, pos, end token.Pos) bool

func (*PosFilter) IsFiltered

func (f *PosFilter) IsFiltered(pos token.Pos) bool

type Report

type Report struct {
	// contains filtered or unexported fields
}

func (*Report) ToDiagReport

func (r *Report) ToDiagReport() analysis.Diagnostic

func (*Report) ToIssue

func (r *Report) ToIssue(fset *token.FileSet) Issue

type Result

type Result struct {
	From string
	To   string
}

Result contains source code (from) and suggested change (to)

func Process

func Process(info *types.Info, filter *PosFilter, n ast.Node, cfg *Config) (*Result, error)

func (*Result) Skipped

func (r *Result) Skipped() bool

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL