protosetter

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2026 License: MIT Imports: 14 Imported by: 0

README

protosetter

Welcome to the protosetter project!

Overview

protosetter 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.

protosetter addresses this issue by suggesting use of setter methods for field updates.

It is recommended to use protogetter in conjunction with protosetter to ensure safe access to nested protobuf fields.

How does it work?

protosetter analyzes your Go code and helps detect direct protobuf field writes.
The linter suggests using setters:

m.GetFoo().GetBar().SetBaz(value)

instead of direct field writes:

m.Foo.Bar.Baz = value

And you will then only need to perform a nil check before writing to the final field:

if m.GetFoo().GetBar() != nil {
    m.GetFoo().GetBar().SetBaz(value)
}

instead of:

if m.Foo != nil {
    if m.Foo.Bar != nil {
        if m.Foo.Bar != nil {
            m.Foo.Bar.Baz = value
        }
    }
}

which simplifies the code and makes it more reliable.

Usage

Integration with golangci-lint is planned.

Standalone usage

Installation
go install github.com/galexrt/protosetter/cmd/protosetter@latest
Direct run

To run the linter:

protosetter ./...

Or to apply suggested fixes directly:

protosetter --fix ./...

License

Based upon the code of protogetter by @ghostiam which is licensed under the MIT License.

Licensed under the MIT License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewAnalyzer

func NewAnalyzer(cfg *Config) *analysis.Analyzer

func Run

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

Types

type Config

type Config struct {
	SkipGeneratedBy         []string
	SkipFiles               []string
	SkipAnyGenerated        bool
	ReplaceFirstArgInAppend bool
}

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

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 ProcessDeprecated

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

func (*Result) Skipped

func (r *Result) Skipped() bool

Directories

Path Synopsis
cmd
protosetter command

Jump to

Keyboard shortcuts

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