analyzer

package module
v0.0.0-...-c832f2a Latest Latest
Warning

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

Go to latest
Published: Dec 24, 2024 License: MIT Imports: 5 Imported by: 0

README

go-enum-linter

Go Enum Linter and Styles

Problem Statement

In Go, enums are typically implemented using type aliases or type definitions with constant values, like this:

package task
type Status int
const (
    Done Status = iota
    InProgress
    ToDo
)

However, this implementation is not truly type-safe. The Go compiler allows several unsafe operations that can break enum semantics:

package main
type MyTask struct {
    status task.Status
}
const AnotherTaskStatus task.Status = 1111 // Arbitrary values allowed
func main() {
    var taskStatusA task.Status  // Zero-value initialization
    taskStatusB := 238             
    printStatus(taskStatusB)
    printStatus(238)             // Literal values accepted as parameters
    _ = MyTask{
        status: 348123893,       // Any literal value accepted in structs
    }
}

func printStatus(taskStatus task.Status) {
    fmt.Println(taskStatus)
}

Solutions: Type-Safe Enum Guidelines

go-enum-linter enforces type-safe enum patterns through the following rules:

  1. Enum definitions must be in files with the .enum.go suffix
  2. Only within .enum.go files:
    • Define enum types (via type aliases or definitions)
    • Define enum constants / vars
    • Assign literal values to enum types
    • Define constructor functions for raw value conversion (if needed)
// Constructor for safe conversion from raw values
func NewStatus(value int) (Status, error) {
    s := Status(value)
    switch s {
    case Done, InProgress, ToDo:
        return s, nil
    default:
        return Status(0), fmt.Errorf("invalid status value: %d", value)
    }
}
  1. Outside of .enum.go files, the following are prohibited:
    • Defining new enum values
    • Zero-value initialization of enum variables
    • Direct integer assignments to enum types
    • Using integer literals where enum types are expected
    • Converting raw values to enum types without using constructors defined in .enum.go

Linter for the Guidelines

go-enum-linter helps you enforce these type-safe enum guidelines in your codebase.

The linter is available as a plugin for golangci-lint. First, ensure you have golangci-lint installed:

# Install golangci-lint
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
Usage
  1. Enable the linter in your .golangci.yml:
linters:
  enable:
    - go-enum-linter

linters-settings:
  go-enum-linter:
    # configuration options if any
  1. Run golangci-lint:
golangci-lint run

The linter will report violations of the enum guidelines, such as:

  • Invalid enum value assignments outside of .enum.go files
  • Direct integer conversions without constructor functions
  • Zero-value initializations
  • And other violations of the guidelines above
Installation manual

TODO: provide manual CLI installation

Documentation

Index

Constants

This section is empty.

Variables

View Source
var GoEnumLintAnalyzer = &analysis.Analyzer{
	Name: "GoEnumLinter",
	Doc:  "Analyze enums and their usage",
	Run:  analyzeEnum,
}

Functions

This section is empty.

Types

type EnumData

type EnumData struct {
	PackageName string
	Types       []string            // Type of enum
	Values      map[string][]string // Values of the enum type
}

Directories

Path Synopsis
cmd
go-enum-linter command

Jump to

Keyboard shortcuts

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