### Install Forbidigo Binary Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/getting-started.md Install the forbidigo linter using go install. This is the simplest way to get the command-line tool. ```bash go install github.com/ashanbrown/forbidigo/v2@latest ``` -------------------------------- ### Golangci-lint Configuration with Multiple Patterns Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/analyzer-integration.md This example shows how to configure forbidigo in .golangci.yml, including multiple patterns and a simple 'print' pattern. ```yaml linters: - forbidigo linters-settings: forbidigo: forbid: - p: ^ginkgo\.F[A-Z].*$ msg: "do not commit focused tests" - p: ^spew\.Dump$ - p: ^print$ run: tests: true exclude-dirs: - vendor ``` -------------------------------- ### Type-Aware Matching Examples Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/getting-started.md Demonstrates how forbidigo's type analysis works with package aliases and import statements. ```go import "database/sql" var db *sql.DB db.Exec() // Matches // Also with alias import sql2 "database/sql" var db sql2.DB db.Exec() // Matches (without type analysis, wouldn't match) // Also with import . import . "database/sql" var db DB db.Exec() // Matches ``` -------------------------------- ### Golangci-lint Configuration Example Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/analyzer-integration.md Configure forbidigo patterns and messages within your .golangci.yml file. This allows for centralized pattern management. ```yaml linters: - forbidigo linters-settings: forbidigo: forbid: - p: ^fmt\.Print.* msg: "do not use fmt.Print in production code" - p: ^spew\.Dump$ msg: "do not dump variables to stdout" ``` -------------------------------- ### Include Godoc Examples Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/options.md When false, godoc examples are included in the linter's checks. This requires explicit configuration. ```go linter, err := forbidigo.NewLinter( []string{`^fmt\.Print.*$`}, forbidigo.OptionExcludeGodocExamples(false), ) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Debug Logging Example Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/run-config.md Illustrates configuring the DebugLog field in RunConfig to capture and display linter debug messages. ```go config := forbidigo.RunConfig{ Fset: fset, TypesInfo: typesInfo, DebugLog: func(format string, args ...interface{}) { fmt.Printf("[forbidigo] " + format + "\n", args...) }, } // This will produce output like: // [forbidigo] code.go:5:2: match [fmt.Println], package "fmt" // [forbidigo] code.go:8:2: match [print], package "" ``` -------------------------------- ### Install Forbidigo Source: https://github.com/ashanbrown/forbidigo/blob/master/README.md Use this command to install forbidigo as a standalone tool. Ensure your Go environment is set up correctly. ```bash go install github.com/ashanbrown/forbidigo@latest ``` -------------------------------- ### Run Linter with Full Configuration Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/linter.md Use `RunWithConfig` for advanced pattern matching on AST nodes, supporting type analysis, exclusion of Godoc examples, and permit directives. ```go func (l *Linter) RunWithConfig(config RunConfig, nodes ...ast.Node) ([]Issue, error) ``` ```go package main import ( "go/ast" "go/parser" "go/token" "log" "github.com/ashanbrown/forbidigo/v2/forbidigo" ) func main() { fset := token.NewFileSet() file, err := parser.ParseFile(fset, "example.go", src, 0) if err != nil { log.Fatal(err) } linter, err := forbidigo.NewLinter([]string{`^fmt\.Print.*$`}) if err != nil { log.Fatal(err) } issues, err := linter.RunWithConfig( forbidigo.RunConfig{Fset: fset}, file, ) if err != nil { log.Fatal(err) } for _, issue := range issues { log.Println(issue) } } ``` -------------------------------- ### Debug Logging Output Example Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/getting-started.md Example output from forbidigo's debug logging, showing which patterns matched specific code elements. ```text [forbidigo] main.go:5:2: match [fmt.Println], package "fmt" [forbidigo] main.go:8:2: match [print], package "" ``` -------------------------------- ### Literal Matching Example Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/patterns.md Demonstrates literal pattern matching where patterns must exactly match the source code. Import aliases prevent matches. ```Go // With pattern: ^fmt\.Print.* fmt.Println("x") // MATCHES fmt.Printf("x") // MATCHES fmt.Print("x") // MATCHES // With import alias: import fmt2 "fmt" fmt2.Println("x") // DOES NOT MATCH (source says "fmt2" not "fmt") ``` -------------------------------- ### Configure Linter Options Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/configuration.md Instantiate a Linter with specific configurations using functional options. Options control exclusion of godoc examples, ignoring permit directives, and enabling type analysis. ```go linter, err := forbidigo.NewLinter( patterns, forbidigo.OptionExcludeGodocExamples(true), forbidigo.OptionIgnorePermitDirectives(false), forbidigo.OptionAnalyzeTypes(true), ) ``` -------------------------------- ### Type Analysis Example Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/00-START-HERE.md Illustrates how Forbidigo matches against canonical package-qualified names, showing a non-match without and a match with correct import aliasing. ```go Without: import fmt2 "fmt"; fmt2.Println() ❌ (no match) ``` ```go With: import fmt2 "fmt"; fmt2.Println() ✅ (matches) ``` -------------------------------- ### Configure Linter to Exclude Godoc Examples Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/package-structure.md Use `OptionExcludeGodocExamples` to configure the linter to ignore godoc examples. This option takes a boolean value. ```go func OptionExcludeGodocExamples(bool) Option ``` -------------------------------- ### Direct API Usage of Forbidigo with Full Configuration Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/configuration.md Integrate Forbidigo directly into your Go application using its API. This example demonstrates creating a new linter with custom patterns and options, loading Go packages, and running the linter with detailed configuration. ```go package main import ( "go/parser" "go/token" "log" "golang.org/x/tools/go/packages" "github.com/ashanbrown/forbidigo/v2/forbidigo" ) func main() { patterns := []string{ `^fmt\.Print.*$`, `^spew\.Dump$`, `{p: "^database/sql\.DB\.Exec$", msg: "use prepared statements"}`, } linter, err := forbidigo.NewLinter( patterns, forbidigo.OptionExcludeGodocExamples(true), forbidigo.OptionIgnorePermitDirectives(false), forbidigo.OptionAnalyzeTypes(true), ) if err != nil { log.Fatalf("Failed to create linter: %v", err) } cfg := packages.Config{ Mode: packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedDeps, } pkgs, err := packages.Load(&cfg, "./...") if err != nil { log.Fatal(err) } for _, pkg := range pkgs { nodes := make([]ast.Node, 0, len(pkg.Syntax)) for _, f := range pkg.Syntax { nodes = append(nodes, f) } issue, err := linter.RunWithConfig( forbidigo.RunConfig{ Fset: pkg.Fset, TypesInfo: pkg.TypesInfo, DebugLog: func(format string, args ...interface{}) { log.Printf("[forbidigo] "+format, args...) }, }, nodes..., ) if err != nil { log.Fatal(err) } for _, issue := range issues { log.Println(issue) } } } ``` -------------------------------- ### UsedIssue Details Method (without custom message) Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/issue.md Example of the Details method for UsedIssue when no custom message is provided, falling back to the matching pattern. ```go issue2 := UsedIssue{ identifier: "print", pattern: `^print$`, customMsg: "", } fmt.Println(issue2.Details()) ``` -------------------------------- ### OptionExcludeGodocExamples Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/options.md Controls whether code in godoc examples is excluded from checking. When true, godoc examples are excluded. When false, they are included. The default behavior is to exclude godoc examples. ```APIDOC ## OptionExcludeGodocExamples ### Description Controls whether code in godoc examples is excluded from checking. ### Function Signature ```go func OptionExcludeGodocExamples(o bool) Option ``` ### Parameters #### Path Parameters - **o** (bool) - Required - When true, godoc examples are excluded. When false, they are included. ### Default Behavior - **Default**: `true` (godoc examples are excluded) ### Example ```go // Exclude godoc examples (default) linter, err := forbidigo.NewLinter( []string{`^fmt\.Print.*$`}, forbidigo.OptionExcludeGodocExamples(true), ) if err != nil { log.Fatal(err) } // Include godoc examples linter, err := forbidigo.NewLinter( []string{`^fmt\.Print.*$`}, forbidigo.OptionExcludeGodocExamples(false), ) if err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### UsedIssue String Method Example Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/issue.md Demonstrates the String method of UsedIssue, which returns a fully formatted issue message including details and position. ```go issue := /* obtained from linter RunWithConfig */ log.Println(issue.String()) ``` -------------------------------- ### Run forbidigo Without Excluding Godoc Examples Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/configuration.md Execute forbidigo to check godoc examples by disabling the exclusion flag, targeting fmt.Print functions. ```bash forbidigo -exclude_godoc_examples=false ^fmt\.Print.*$ -- ./... ``` -------------------------------- ### Permit Directives in Forbidigo Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/examples.md Provides examples of correct and incorrect usage of permit directives in forbidigo. Ensure the directive is on the same line, matches the text exactly, and that permit directives are not ignored by the linter options. ```go // This works fmt.Println("x") //permit:fmt.Println // This doesn't (option disabled) // When OptionIgnorePermitDirectives(true) is set // This doesn't (different text) fmt2.Println("x") //permit:fmt.Println // (should be: //permit:fmt2.Println) ``` -------------------------------- ### Basic Forbidigo CLI Usage Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/00-START-HERE.md Run forbidigo from the command line to lint files. This example checks for usages of fmt.Print and its variants in the current directory and subdirectories. ```bash forbidigo ^fmt\.Print.*$ -- ./... ``` -------------------------------- ### UsedIssue Details Method (with custom message) Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/issue.md Example of the Details method for UsedIssue when a custom message is provided, showing a specific reason for the issue. ```go issue := UsedIssue{ identifier: "fmt.Println", pattern: `^fmt\.Println$`, customMsg: "do not write to stdout", } fmt.Println(issue.Details()) ``` -------------------------------- ### Define complex patterns Source: https://github.com/ashanbrown/forbidigo/blob/master/README.md Examples of JSON and YAML configurations for advanced pattern matching with custom error messages. ```json {p: "^fmt\\.Println$", msg: "do not write to stdout"} ``` ```yaml {p: ^fmt\.Println$, msg: do not write to stdout, } ``` ```json {p: ^fmt\.Println$, msg: do not write to stdout} ``` ```yaml p: ^fmt\.Println$ msg: do not write to stdout ``` -------------------------------- ### Basic forbidigo Configuration Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/examples.md Configure forbidigo to ban specific patterns like fmt.Print.* and spew.Dump. This setup is useful for initial project-wide restrictions. ```yaml linters: - forbidigo linters-settings: forbidigo: forbid: - p: ^fmt\.Print.*$ - p: ^spew\.Dump$ ``` -------------------------------- ### Basic Standalone Usage of Forbidigo Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/configuration.md Use Forbidigo from the command line with default settings or custom patterns. The first example uses defaults to catch debug print statements, while the second specifies custom patterns to exclude. ```bash # Use defaults to catch debug print statements forbidigo -- ./cmd/... ./pkg/... ``` ```bash # Custom patterns forbidigo -set_exit_status ^spew\.Dump$ ^fmt\.Print.*$ -- ./... ``` -------------------------------- ### Basic Analysis with RunConfig Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/run-config.md Demonstrates initializing the linter with a minimal RunConfig containing only the file set for basic analysis. ```go package main import ( "go/ast" "go/parser" "go/token" "log" "github.com/ashanbrown/forbidigo/v2/forbidigo" ) func main() { fset := token.NewFileSet() file, err := parser.ParseFile(fset, "code.go", sourceCode, 0) if err != nil { log.Fatal(err) } linter, err := forbidigo.NewLinter([]string{`^fmt\.Print.*$`}) if err != nil { log.Fatal(err) } // Minimal config: only file set issue, err := linter.RunWithConfig( forbidigo.RunConfig{ Fset: fset, }, file, ) if err != nil { log.Fatal(err) } for _, issue := range issues { log.Println(issue) } } ``` -------------------------------- ### Integrating with go/packages for RunConfig Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/run-config.md Shows how to use golang.org/x/tools/go/packages to load package information and construct a RunConfig. ```go import ( "golang.org/x/tools/go/packages" ) cfg := packages.Config{ Mode: packages.NeedSyntax | packages.NeedName | packages.NeedFiles | packages.NeedTypes, } // Add these for AnalyzeTypes support if analyzeTypes { cfg.Mode |= packages.NeedTypesInfo | packages.NeedDeps } pkgs, err := packages.Load(&cfg, "./...") if err != nil { log.Fatal(err) } for _, pkg := range pkgs { runConfig := forbidigo.RunConfig{ Fset: pkg.Fset, TypesInfo: pkg.TypesInfo, // Use nil if AnalyzeTypes is disabled } // Use runConfig with linter } ``` -------------------------------- ### Get Default Forbidden Patterns Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/package-structure.md Retrieve a slice of default forbidden patterns using `DefaultPatterns`. This provides a starting set of rules for the linter. ```go func DefaultPatterns() []string ``` -------------------------------- ### Exclude Godoc Examples Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/options.md When true, godoc examples are excluded from checking. This is the default behavior. ```go linter, err := forbidigo.NewLinter( []string{`^fmt\.Print.*$`}, forbidigo.OptionExcludeGodocExamples(true), ) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Basic Linter Usage Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/INDEX.md Initialize a linter with a list of forbidden patterns and run it on a file. Issues found will be logged. ```go linter, _ := forbidigo.NewLinter([]string{`^fmt\.Print.*$`}) issues, _ := linter.RunWithConfig(forbidigo.RunConfig{Fset: fset}, file) for _, issue := range issues { log.Println(issue) } ``` -------------------------------- ### Direct API Usage Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/INDEX.md Initialize the linter with patterns and options, then run it against code nodes. Refer to the forbidigo/forbidigo, forbidigo/patterns, and forbidigo/config_options packages. ```go linter, err := forbidigo.NewLinter(patterns, options...) issues, err := linter.RunWithConfig(config, nodes...) ``` -------------------------------- ### Permit Directive in Godoc Example Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/permit-directives.md Permit directives function within godoc examples when `ExcludeGodocExamples` is set to false, allowing specific forbidden identifiers to be used while still being checked by the linter. ```go // Example_formatOutput shows how to format output (this is still checked // if ExcludeGodocExamples is false) func Example_formatOutput() { fmt.Println("hello") //permit:fmt.Println // Output: hello } ``` -------------------------------- ### Forbid All Format Printing Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/patterns.md Use this pattern to forbid all functions starting with 'fmt.Print'. ```go // Forbid all format printing `^fmt\.Print.*$` ``` -------------------------------- ### Basic Linting with Forbidigo Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/examples.md Demonstrates how to create a new linter, parse Go source code, and run the analysis to find forbidden patterns. Ensure the 'fmt' package is imported. ```go package main import ( "go/parser" "go/token" "log" "github.com/ashanbrown/forbidigo/v2/forbidigo" ) func main() { // Create linter linter, err := forbidigo.NewLinter([]string{`^fmt\.Print.*$`}) if err != nil { log.Fatal(err) } // Parse source code fset := token.NewFileSet() file, err := parser.ParseFile(fset, "main.go", ` package main import "fmt" func main() { fmt.Println("hello") } `, 0) if err != nil { log.Fatal(err) } // Run analysis issue, err := linter.RunWithConfig( forbidigo.RunConfig{Fset: fset}, file, ) if err != nil { log.Fatal(err) } // Print results for _, issue := range issues { log.Println(issue) } // Output: use of `fmt.Println` forbidden by pattern `^fmt\.Print.*$` at main.go:5:2 } ``` -------------------------------- ### Add Forbidigo as a Library Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/getting-started.md Include forbidigo as a dependency in your Go project using go get. ```bash go get github.com/ashanbrown/forbidigo/v2 ``` -------------------------------- ### Resolve struct methods and fields Source: https://github.com/ashanbrown/forbidigo/blob/master/README.md Example showing how forbidigo resolves struct methods to their package-qualified names. ```go import "example.com/some/pkg" // pkg uses `package somepkg` s := somepkg.SomeStruct{} s.SomeMethod() // -> somepkg.SomeStruct.SomeMethod ``` -------------------------------- ### Run analysis with configuration Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/README.md Execute the linter against provided AST nodes using a specific configuration, including file set and type information. This is used for programmatic analysis. ```go issues, err := linter.RunWithConfig( forbidigo.RunConfig{ Fset: fset, TypesInfo: typesInfo, }, astNodes... ) ``` -------------------------------- ### Run Linter Analysis with Configuration Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/package-structure.md The `RunWithConfig` method performs AST traversal using a provided `RunConfig` for analysis. This is the preferred method for running the linter. ```go func (l *Linter) RunWithConfig(config RunConfig, nodes ...ast.Node) ([]Issue, error) ``` -------------------------------- ### Analysis with Type Information and Debug Logging Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/run-config.md Shows how to configure RunConfig with file set, type information, and a custom debug log function for advanced analysis. ```go package main import ( "go/ast" "go/parser" "go/token" "log" "golang.org/x/tools/go/packages" "github.com/ashanbrown/forbidigo/v2/forbidigo" ) func main() { cfg := packages.Config{ Mode: packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo, } pkgs, err := packages.Load(&cfg, ".") if err != nil { log.Fatal(err) } linter, err := forbidigo.NewLinter( []string{`^database/sql\.DB\.Exec$`}, forbidigo.OptionAnalyzeTypes(true), ) if err != nil { log.Fatal(err) } pkg := pkgs[0] nodes := make([]ast.Node, 0, len(pkg.Syntax)) for _, f := range pkg.Syntax { nodes = append(nodes, f) } // Full config: file set + type information + debug logging issue, err := linter.RunWithConfig( forbidigo.RunConfig{ Fset: pkg.Fset, TypesInfo: pkg.TypesInfo, DebugLog: func(format string, args ...interface{}) { log.Printf("[DEBUG] " + format, args...) }, }, nodes... ) if err != nil { log.Fatal(err) } for _, issue := range issues { log.Println(issue) } } ``` -------------------------------- ### Combine Linter Options Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/options.md Pass multiple configuration options to `NewLinter` to customize linting rules. Options are applied sequentially; all must succeed for initialization to succeed. ```go linter, err := forbidigo.NewLinter( patterns, forbidigo.OptionExcludeGodocExamples(false), forbidigo.OptionIgnorePermitDirectives(true), forbidigo.OptionAnalyzeTypes(true), ) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Using the Issue Interface Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/issue.md Demonstrates how to access structured information from an Issue object obtained from the linter. ```go var issue forbidigo.Issue = /* obtained from linter */ // Get structured information fmt.Println(issue.Details()) fmt.Println(issue.Position()) fmt.Println(issue.String()) fmt.Println(issue.Pos()) ``` -------------------------------- ### Linter Usage with Type Analysis Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/INDEX.md Initialize a linter with type analysis enabled and run it using package information. This allows for more precise matching based on types. ```go linter, _ := forbidigo.NewLinter( []string{`^database/sql\.DB\.Query$`}, forbidigo.OptionAnalyzeTypes(true), ) issues, _ := linter.RunWithConfig( forbidigo.RunConfig{Fset: pkg.Fset, TypesInfo: pkg.TypesInfo}, pkg.Syntax... ) ``` -------------------------------- ### Direct API Usage Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/INDEX.md Initialize the forbidigo linter with custom patterns and options, then run it against a set of Go nodes. ```APIDOC ## Direct API Usage ### Description Initialize the forbidigo linter with custom patterns and options, then run it against a set of Go nodes. ### Method Signature ```go linter, err := forbidigo.NewLinter(patterns, options...) issues, err := linter.RunWithConfig(config, nodes...) ``` ### Parameters `forbidigo.NewLinter`: - `patterns` ([]string): A list of patterns to forbid. - `options` ([]LinterOption): Optional configuration options for the linter. `linter.RunWithConfig`: - `config` (Config): The configuration for the analysis. - `nodes` ([]ast.Node): A list of AST nodes to analyze. ``` -------------------------------- ### Run (Deprecated) Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/linter.md Runs the linter on AST nodes using only a file set. This method is deprecated and `RunWithConfig` should be used instead. ```APIDOC ## Run (Deprecated) ### Description Runs the linter on AST nodes using only a file set. This method is deprecated; use `RunWithConfig` instead. ### Signature ```go func (l *Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **fset** (`*token.FileSet`) - Required - File set containing position information for the AST nodes. - **nodes** (`...ast.Node`) - Required - AST nodes to analyze (typically `*ast.File` from parsed Go source). ### Returns - `[]Issue`: List of issues found during analysis. - `error`: Non-nil if analysis encounters an error. ### Notes This method is deprecated. Use `RunWithConfig` instead as it supports additional pattern matching modes that require type information. ``` -------------------------------- ### Combining Linter Options Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/options.md Demonstrates how to pass multiple options to `forbidigo.NewLinter` to customize linting behavior. Options are applied sequentially, and all must succeed for the linter initialization to be successful. ```APIDOC ## Combining Options Multiple options can be passed to `NewLinter`: ```go linter, err := forbidigo.NewLinter( patterns, forbidigo.OptionExcludeGodocExamples(false), forbidigo.OptionIgnorePermitDirectives(true), forbidigo.OptionAnalyzeTypes(true), ) if err != nil { log.Fatal(err) } ``` Options are applied in order and all must succeed for `NewLinter` to succeed. ``` -------------------------------- ### Get Default Patterns Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/patterns.md Retrieves the default set of patterns used by Forbidigo when no custom patterns are provided. These defaults are useful for removing common debug statements. ```go forbidigo.DefaultPatterns() // Returns: []string{`^(fmt\.Print(|f|ln)|print|println)$`} ``` -------------------------------- ### Type-Aware Linting with Forbidigo Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/examples.md Demonstrates how to enable type analysis for more accurate linting, allowing patterns to match based on types rather than just literal source code. This requires loading packages with type information. ```go package main import ( "go/parser" "go/token" "log" "golang.org/x/tools/go/packages" "github.com/ashanbrown/forbidigo/v2/forbidigo" ) func main() { // Create linter with type analysis enabled linter, err := forbidigo.NewLinter( []string{`^database/sql\.DB\.Query$`}, forbidigo.OptionAnalyzeTypes(true), ) if err != nil { log.Fatal(err) } // Load packages with type information cfg := packages.Config{ Mode: packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedDeps, } pkgs, err := packages.Load(&cfg, "./...") if err != nil { log.Fatal(err) } // Run analysis for _, pkg := range pkgs { nodes := make([]interface{}, 0, len(pkg.Syntax)) for _, f := range pkg.Syntax { nodes = append(nodes, f) } issue, err := linter.RunWithConfig( forbidigo.RunConfig{ Fset: pkg.Fset, TypesInfo: pkg.TypesInfo, }, pkg.Syntax... ) if err != nil { log.Fatal(err) } for _, issue := range issues { log.Println(issue) } } } ``` -------------------------------- ### Get Default Linter Patterns Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/linter.md Retrieve the default list of patterns used by the linter when no specific patterns are provided. These patterns are designed to eliminate common debug statements. ```go func DefaultPatterns() []string ``` ```go patterns := forbidigo.DefaultPatterns() // patterns now contains: ["^(fmt\.Print(|f|ln)|print|println)$"] ``` -------------------------------- ### Run golangci-lint Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/getting-started.md Execute golangci-lint to run all configured linters, including forbidigo, against your project. ```bash golangci-lint run ./... ``` -------------------------------- ### Create a New Linter Instance Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/linter.md Use `NewLinter` to create a linter with custom forbidden patterns and optional configurations. It returns a configured linter or an error if patterns are invalid. ```go func NewLinter(patterns []string, options ...Option) (*Linter, error) ``` ```go package main import ( "log" "github.com/ashanbrown/forbidigo/v2/forbidigo" ) func main() { linter, err := forbidigo.NewLinter( []string{`^fmt\.Println$`, `^print$`}, forbidigo.OptionAnalyzeTypes(true), ) if err != nil { log.Fatalf("Failed to create linter: %v", err) } // linter is ready to use } ``` -------------------------------- ### Define Analyzer Configuration Struct Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/package-structure.md The `analyzer` struct stores configuration extracted from command-line flags and manages the analysis run. It holds patterns, flags for permit directives, example inclusion, type analysis, and a debug logging function. ```go type analyzer struct { patterns []string usePermitDirective bool includeExamples bool analyzeTypes bool debugLog func(format string, args ...interface{}) } ``` -------------------------------- ### Method and Field Matching with Type Analysis Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/patterns.md Shows how type analysis resolves method calls like 'db.Exec()' to the fully qualified pattern 'database/sql.DB.Exec' when 'analyze_types' is enabled and the package is specified. ```go // Pattern: ^database/sql.DB.Exec$ // With analyze_types=true and pkg="^database/sql$" var db *sql.DB db.Exec() // Matches: expanded to "database/sql.DB.Exec" ``` -------------------------------- ### Identifier Matching with Type Analysis Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/patterns.md Demonstrates how type analysis expands simple patterns like '^fmt.Print$' to match qualified identifiers, even with different import aliases or dot imports. ```go // Pattern: ^fmt.Print$ import fmt "fmt" fmt.Print() // Matches: expanded to "fmt.Print" import fmt2 "fmt" fmt2.Print() // Matches: expanded to "fmt.Print" import . "fmt" Print() // Matches both "fmt.Print" and "Print" ``` -------------------------------- ### RunWithConfig Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/linter.md Runs the linter on AST nodes with full configuration for advanced pattern matching, including type analysis and directive support. ```APIDOC ## RunWithConfig ### Description Runs the linter on AST nodes with full configuration for advanced pattern matching. ### Signature ```go func (l *Linter) RunWithConfig(config RunConfig, nodes ...ast.Node) ([]Issue, error) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **config** (`RunConfig`) - Required - Configuration object containing file set, type information, and debug logging. - **nodes** (`...ast.Node`) - Required - AST nodes to analyze (typically `*ast.File` from parsed Go source). ### Returns - `[]Issue`: List of issues found during analysis. Empty slice if no issues found. - `error`: Non-nil if analysis encounters an error. ### Behavior - When `AnalyzeTypes` is enabled in configuration, identifiers are resolved to their canonical names using type information, enabling matching against import aliases and package-qualified names. - Godoc examples are excluded from checking when `ExcludeGodocExamples` is true (default). - Whole file examples (files ending in `_test.go` containing exactly one example function and no test/benchmark functions) are skipped entirely. - The `permit` directive (`//permit:identifier`) can suppress individual matches unless `IgnorePermitDirectives` is true. ### Example ```go package main import ( "go/ast" "go/parser" "go/token" "log" "github.com/ashanbrown/forbidigo/v2/forbidigo" ) func main() { fset := token.NewFileSet() file, err := parser.ParseFile(fset, "example.go", src, 0) if err != nil { log.Fatal(err) } linter, err := forbidigo.NewLinter([]string{`^fmt.Print.*$`}) if err != nil { log.Fatal(err) } issue, err := linter.RunWithConfig( forbidigo.RunConfig{Fset: fset}, file, ) if err != nil { log.Fatal(err) } for _, issue := range issues { log.Println(issue) } } ``` ``` -------------------------------- ### Standalone CLI Usage Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/INDEX.md Use the forbidigo binary directly from the command line, specifying flags, patterns, and packages. ```bash forbidigo [flags] patterns -- packages ``` -------------------------------- ### Forbidigo - Functional Options Pattern for Configuration Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/package-structure.md Demonstrates configuring a new Linter instance using the functional options pattern. This pattern allows for flexible and composable configuration. ```go linter, err := forbidigo.NewLinter( patterns, forbidigo.OptionExcludeGodocExamples(true), forbidigo.OptionAnalyzeTypes(true), ) ``` -------------------------------- ### Handle dot imports Source: https://github.com/ashanbrown/forbidigo/blob/master/README.md Shows how dot imports are resolved to both the package-qualified name and the literal identifier. ```go import . "github.com/onsi/ginkgo/v2" FIt(...) // -> ginkgo.FIt, FIt ``` -------------------------------- ### Package Matching with analyze_types=true Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/patterns.md Illustrates filtering matches by package import path using the 'pkg' field when analyze_types is enabled. This ensures matches are specific to a particular package. ```Go Pattern: {p: "^Exec$", pkg: "^database/sql$"} ``` -------------------------------- ### Run Linter on AST Nodes (Deprecated) Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/linter.md The deprecated `Run` method analyzes AST nodes using only a file set. Use `RunWithConfig` for advanced pattern matching. ```go func (l *Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) ``` -------------------------------- ### Troubleshooting Import Alias Matching Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/examples.md Illustrates how to resolve issues where forbidigo patterns do not match code using import aliases. Enabling type analysis is crucial for correct matching in such cases. ```bash # Before: doesn't match fmt2.Println forbidigo -p '^fmt\.Println$' -- ./... # After: matches both fmt.Println and fmt2.Println forbidigo -analyze_types -p '^fmt\.Println$' -- ./... ``` -------------------------------- ### List All Markdown and Text Files Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/COMPLETION_SUMMARY.txt Command to list all markdown and text files within the output directory, sorted alphabetically. ```bash find /workspace/home/output -type f -name "*.md" -o -name "*.txt" | sort ``` -------------------------------- ### Linter Creation and Configuration Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/README.md Functions to create a new Linter instance, retrieve default patterns, and configure linter options. ```APIDOC ## NewLinter ### Description Creates a new Linter instance with the specified patterns and options. ### Signature `NewLinter(patterns []string, options []Option) (*Linter, error)` ### Parameters - `patterns` ([]string) - A list of patterns to forbid. - `options` ([]Option) - A list of configuration options for the linter. ## DefaultPatterns ### Description Retrieves the default set of patterns used by Forbidigo. ### Signature `DefaultPatterns() []string` ## Option Interface ### Description An interface for configuring Linter options. ### Methods - `OptionExcludeGodocExamples(bool) Option`: Configures whether to exclude GoDoc examples from analysis. - `OptionIgnorePermitDirectives(bool) Option`: Configures whether to ignore `//permit:` directives. - `OptionAnalyzeTypes(bool) Option`: Configures whether to enable type-aware analysis. ``` -------------------------------- ### Forbidigo - Visitor Pattern for AST Traversal Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/package-structure.md Illustrates the use of the AST visitor pattern for traversing the Abstract Syntax Tree. This is used internally by forbidigo to collect issues. ```go visitor := visitor{...} ast.Walk(&visitor, node) ``` -------------------------------- ### Run forbidigo via CLI Source: https://github.com/ashanbrown/forbidigo/blob/master/README.md Basic command-line syntax for executing the linter with patterns and package targets. ```bash forbidigo [flags...] patterns... -- packages... ``` -------------------------------- ### Compact YAML Pattern (Single Line) Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/patterns.md Structured patterns can also be defined on a single line using a compact YAML format, suitable for inline configurations. ```go `{p: \"^fmt\\.Println$\", msg: \"do not write to stdout\"}` ``` -------------------------------- ### Enable Type-Aware Matching (CLI) Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/getting-started.md Activate forbidigo's type analysis capabilities with the -analyze_types flag for more precise matching, especially with package aliases. ```bash forbidigo -analyze_types -p '^database/sql\.DB\.Exec$' -- ./... ``` -------------------------------- ### golangci-lint Integration Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/INDEX.md Create a new analyzer instance for integration with golangci-lint. ```APIDOC ## golangci-lint Integration ### Description Create a new analyzer instance for integration with golangci-lint. ### Method Signature ```go analyzer := analyzer.NewAnalyzer() ``` ### Package `forbidigo/pkg/analyzer` ``` -------------------------------- ### Interface Method Resolution Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/patterns.md Explains that when matching interface methods (e.g., '^pkg.MyInterface.Method$'), the resolution is to the interface type, not the concrete implementation type. ```go // Pattern: ^pkg.MyInterface.Method$ type MyInterface interface { Method() } var i MyInterface = SomeImplementation{} i.Method() // Resolved as "pkg.MyInterface.Method" // (not the concrete implementation type) ``` -------------------------------- ### Literal vs. Semantic Matching with Forbidigo Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/examples.md Demonstrates the difference between literal string matching and type-aware semantic matching in forbidigo. Use type analysis for more accurate matching across package aliases. ```bash $ forbidigo -p '^fmt\.Println$' -- ./... # Matches: fmt.Println # Does not match: fmt2.Println (even if fmt2 is an alias for fmt) ``` ```bash $ forbidigo -analyze_types -p '^fmt\.Println$' -- ./... # Matches: fmt.Println # Also matches: fmt2.Println (resolved to canonical name) # Also matches: Println (if imported with import .) ``` -------------------------------- ### Forbidigo Linting with Debug Logging Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/examples.md Shows how to enable debug logging during linting by providing a custom DebugLog function in the RunConfig. This helps in understanding the matching process. ```go issues, err := linter.RunWithConfig( forbidigo.RunConfig{ Fset: fset, DebugLog: func(format string, args ...interface{}) { log.Printf("[DEBUG] " + format, args...) }, }, file, ) ``` -------------------------------- ### Linter Execution Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/README.md Methods for running the Linter against Go source code nodes. ```APIDOC ## Linter Type ### Description Represents the Forbidigo linter. ### Methods - `Run(fset *token.FileSet, nodes []*ast.File) ([]Issue, error)`: Runs the linter on a set of AST files using the provided file set. - `RunWithConfig(config RunConfig, nodes []*ast.File) ([]Issue, error)`: Runs the linter with a specific configuration on a set of AST files. ``` -------------------------------- ### Linter.RunWithConfig Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/types.md Analyzes a given set of AST nodes using the Linter with the provided RunConfig. This is the primary method for performing analysis. ```APIDOC ## Linter.RunWithConfig ### Description Performs analysis on the provided AST nodes using the linter's configured patterns and the specified run configuration. This method is used for direct analysis. ### Signature `RunWithConfig(config RunConfig, nodes ...ast.Node) ([]Issue, error)` ### Parameters - **config** (`RunConfig`) - The configuration for the analysis run, including file set and optional type information or debug logging. - **nodes** (`...ast.Node`) - A variadic list of AST nodes to analyze. ``` -------------------------------- ### Browse Directory Contents Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/COMPLETION_SUMMARY.txt Command to list the contents of a directory in a long listing format, showing details like permissions, owner, size, and modification date. ```bash ls -lh /workspace/home/output/ ``` -------------------------------- ### Enable Type Analysis for Linter Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/options.md Use `OptionAnalyzeTypes(true)` to enable semantic analysis with type information. This requires `RunConfig.TypesInfo` to be provided and `packages.Config` to include `packages.NeedTypesInfo | packages.NeedDeps`. ```go import ( "golang.org/x/tools/go/packages" "github.com/ashanbrown/forbidigo/v2/forbidigo" ) // Create linter with type analysis enabled linter, err := forbidigo.NewLinter( []string{`^database/sql.DB.Exec$`}, forbidigo.OptionAnalyzeTypes(true), ) if err != nil { log.Fatal(err) } // Load packages with required type information cfg := packages.Config{ Mode: packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedDeps, } pkgs, err := packages.Load(&cfg, "./...") if err != nil { log.Fatal(err) } // Run analysis with type info for _, pkg := range pkgs { issue, err := linter.RunWithConfig( forbidigo.RunConfig{ Fset: pkg.Fset, TypesInfo: pkg.TypesInfo, }, pkg.Syntax... ) if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Analyzer Package Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/README.md Provides functionality to create a `golang.org/x/tools/go/analysis` Analyzer. ```APIDOC ## NewAnalyzer ### Description Creates a new `analysis.Analyzer` for Forbidigo. ### Signature `NewAnalyzer() *analysis.Analyzer` ### Returns - `*analysis.Analyzer`: The Forbidigo analyzer. ### Flags This analyzer supports the following flags: - `-p` (repeatable): Specifies a pattern to forbid. - `-examples`: Enables analysis of GoDoc examples. - `-permit`: Enables ignoring permit directives. - `-analyze_types`: Enables type-aware analysis. ``` -------------------------------- ### Using `// nolint:forbidigo` for Suppression Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/permit-directives.md For golangci-lint integration, it is recommended to use the standard `// nolint:forbidigo` directive instead of `//permit` directives. This provides better compatibility and finer control. ```go fmt.Println("x") //nolint:forbidigo spew.Dump(x) //nolint:forbidigo ``` -------------------------------- ### golangci-lint Integration Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/INDEX.md Create a new analyzer for integration with golangci-lint. The relevant package is forbidigo/pkg/analyzer. ```go analyzer := analyzer.NewAnalyzer() ``` -------------------------------- ### Allow Specific Types from Package (CLI) Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/getting-started.md Use forbidigo with a pattern to allow only specific types from a package, demonstrated here with crypto/md5. ```bash forbidigo -p '^crypto/md5\.' -- ./... ``` -------------------------------- ### RunConfig Structure Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/README.md Defines the configuration for running the Linter. ```APIDOC ## RunConfig Struct ### Description Configuration structure for running the Linter. ### Fields - `Fset *token.FileSet`: The file set to use for parsing. - `TypesInfo *types.Info`: Type information for type-aware analysis. - `DebugLog func(...)`: A function for debug logging. ``` -------------------------------- ### Standalone CLI Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/INDEX.md Use the forbidigo command-line interface to check Go packages for forbidden identifiers. ```APIDOC ## Standalone CLI ### Description Use the forbidigo command-line interface to check Go packages for forbidden identifiers. ### Usage ```bash forbidigo [flags] patterns -- packages ``` ### Binary `forbidigo` ``` -------------------------------- ### Configure SQL Query Bans with Type Analysis (YAML) Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/getting-started.md Use a more robust configuration with forbidigo's YAML settings to ban specific methods like 'Exec' on database/sql.DB, suggesting prepared statements. ```yaml linters-settings: forbidigo: forbid: - p: ^Exec$ pkg: ^database/sql$ msg: "use prepared statements" ``` -------------------------------- ### Enable Debug Logging (Programmatic) Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/getting-started.md Configure forbidigo programmatically to enable debug logging, which outputs detailed information about pattern matching. ```go config := forbidigo.RunConfig{ Fset: fset, DebugLog: func(format string, args ...interface{}) { log.Printf("[forbidigo] " + format, args...) }, } issues, err := linter.RunWithConfig(config, file) ``` -------------------------------- ### RunConfig Struct Definition Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/api-reference/run-config.md Defines the structure for linter configuration, including file set, type information, and a debug log function. ```go type RunConfig struct { Fset *token.FileSet TypesInfo *types.Info DebugLog func(format string, args ...interface{}) } ``` -------------------------------- ### Configure Linter for Type Analysis Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/package-structure.md Use `OptionAnalyzeTypes` to enable type analysis for more accurate pattern matching. This option takes a boolean value. ```go func OptionAnalyzeTypes(bool) Option ``` -------------------------------- ### Apply Custom Option Returning Error Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/errors.md Demonstrates how `NewLinter` handles errors originating from a custom option's `apply()` method. This is unlikely with built-in options. ```go // With custom option that returns error customOpt := MyCustomOption{} linter, err := forbidigo.NewLinter(patterns, customOpt) // err = "failed to process options: " ``` -------------------------------- ### Validate Patterns Before Linter Initialization Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/errors.md If a pattern has a syntax error, NewLinter fails. Validate patterns individually before passing them to NewLinter to skip invalid ones. ```go for _, p := range userPatterns { if _, err := forbidigo.NewLinter([]string{p}); err != nil { log.Printf("Skipping invalid pattern %q: %v", p, err) continue } validPatterns = append(validPatterns, p) } linter, err := forbidigo.NewLinter(validPatterns) ``` -------------------------------- ### Canonical Matching with analyze_types=true Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/patterns.md Shows how patterns match canonical package-qualified names when analyze_types is enabled. This includes handling import aliases and dot imports. ```Go // With pattern: ^fmt\.Print.*$ and analyze_types=true fmt.Println("x") // MATCHES fmt2.Println("x") // MATCHES (expanded to "fmt.Println" via type info) import . "fmt" Println("x") // MATCHES (expanded to "fmt.Println") // Also matches pattern ^Println$ ``` -------------------------------- ### RunConfig Configuration for Analysis Source: https://github.com/ashanbrown/forbidigo/blob/master/_autodocs/configuration.md Programmatically configure a specific analysis run using forbidigo.RunConfig. This is useful for advanced scenarios where command-line flags are insufficient. ```go config := forbidigo.RunConfig{ Fset: fset, // Required TypesInfo: typesInfo, // Optional: enables analyze_types features DebugLog: debugLogFunction, // Optional: for debug output } issues, err := linter.RunWithConfig(config, nodes...) ```