-Style definitions for nice terminal layouts. Built with TUIs in mind.
+
Style definitions for nice terminal layouts. Built with TUIs in mind.
-
+
Lip Gloss takes an expressive, declarative approach to terminal rendering.
Users familiar with CSS will feel at home with Lip Gloss.
```go
-
-import "github.com/charmbracelet/lipgloss"
+import "charm.land/lipgloss/v2"
var style = lipgloss.NewStyle().
Bold(true).
@@ -27,9 +25,20 @@ var style = lipgloss.NewStyle().
PaddingLeft(4).
Width(22)
-fmt.Println(style.Render("Hello, kitty"))
+lipgloss.Println(style.Render("Hello, kitty"))
+```
+
+## Installation
+
+```bash
+go get charm.land/lipgloss/v2
```
+> [!TIP]
+>
+> Upgrading from v1? Check out the [upgrade guide](./UPGRADE_GUIDE_V2.md), or
+> point your LLM at it and let it go to town.
+
## Colors
Lip Gloss supports the following color profiles:
@@ -60,45 +69,58 @@ lipgloss.Color("#3C3C3C") // a dark gray
...as well as a 1-bit ASCII profile, which is black and white only.
-The terminal's color profile will be automatically detected, and colors outside
-the gamut of the current palette will be automatically coerced to their closest
-available value.
-
-### Adaptive Colors
-
-You can also specify color options for light and dark backgrounds:
+There are also named constants for the 16 standard ANSI colors:
```go
-lipgloss.AdaptiveColor{Light: "236", Dark: "248"}
+lipgloss.Black
+lipgloss.Red
+lipgloss.Green
+lipgloss.Yellow
+lipgloss.Blue
+lipgloss.Magenta
+lipgloss.Cyan
+lipgloss.White
+lipgloss.BrightBlack
+lipgloss.BrightRed
+lipgloss.BrightGreen
+lipgloss.BrightYellow
+lipgloss.BrightBlue
+lipgloss.BrightMagenta
+lipgloss.BrightCyan
+lipgloss.BrightWhite
```
-The terminal's background color will automatically be detected and the
-appropriate color will be chosen at runtime.
+### Automatically Downsampling Colors
-### Complete Colors
+Some users don't have Truecolor terminals. Other times, output might not
+support color at all (for example, in logs). Lip Gloss was designed to handle
+this gracefully by automatically downsampling colors to the best available
+profile.
-CompleteColor specifies exact values for True Color, ANSI256, and ANSI color
-profiles.
+If you're using Lip Gloss with Bubble Tea, there’s nothing to do. If you're
+using Lip Gloss standalone, just use `lipgloss.Println` or `lipgloss.Sprint`
+(and their variants).
-```go
-lipgloss.CompleteColor{TrueColor: "#0000FF", ANSI256: "86", ANSI: "5"}
-```
+For more, see [advanced color usage](#advanced-color-usage).
-Automatic color degradation will not be performed in this case and it will be
-based on the color specified.
+### Color Utilities
-### Complete Adaptive Colors
-
-You can use `CompleteColor` with `AdaptiveColor` to specify the exact values for
-light and dark backgrounds without automatic color degradation.
+Lip Gloss ships with a handful of handy tools for working with colors:
```go
-lipgloss.CompleteAdaptiveColor{
- Light: CompleteColor{TrueColor: "#d7ffae", ANSI256: "193", ANSI: "11"},
- Dark: CompleteColor{TrueColor: "#d75fee", ANSI256: "163", ANSI: "5"},
-}
+c := lipgloss.Color("#EB4268") // Sriracha sauce color
+dark := lipgloss.Darken(c, 0.5) // dark Sriracha sauce
+light := lipgloss.Lighten(c, 0.35) // light Sriracha sauce
+green := lipgloss.Complementary(c) // greenish Sriracha sauce
+withAlpha := lipgloss.Alpha(c, 0.2) // watered down Sriracha sauce
```
+### Advanced Color Tooling
+
+Lip Gloss also supports color blending, automatically choosing light or dark
+variants of colors at runtime, and a lot more. For details, see [Advanced Color
+Usage](#advanced-color-usage) and [the docs][docs].
+
## Inline Formatting
Lip Gloss supports the usual ANSI text formatting options:
@@ -114,6 +136,34 @@ var style = lipgloss.NewStyle().
Reverse(true)
```
+### Underline Styles
+
+Beyond simple on/off, underlines support multiple styles and custom colors:
+
+```go
+s := lipgloss.NewStyle().
+ UnderlineStyle(lipgloss.UnderlineCurly).
+ UnderlineColor(lipgloss.Color("#FF0000"))
+```
+
+Available styles: `UnderlineNone`, `UnderlineSingle`, `UnderlineDouble`,
+`UnderlineCurly`, `UnderlineDotted`, `UnderlineDashed`.
+
+### Hyperlinks
+
+Styles can render clickable hyperlinks in supporting terminals:
+
+```go
+s := lipgloss.NewStyle().
+ Foreground(lipgloss.Color("#7B2FBE")).
+ Hyperlink("https://charm.land")
+
+lipgloss.Println(s.Render("Visit Charm"))
+```
+
+In unsupported terminals this will degrade gracefully and hyperlinks will
+simply not render.
+
## Block-Level Formatting
Lip Gloss also supports rules for block-level formatting:
@@ -152,6 +202,16 @@ lipgloss.NewStyle().Padding(1, 4, 2)
lipgloss.NewStyle().Margin(2, 4, 3, 1)
```
+You can also customize the characters used for padding and margin fill:
+
+```go
+s := lipgloss.NewStyle().
+ Padding(1, 2).
+ PaddingChar('·').
+ Margin(1, 2).
+ MarginChar('░')
+```
+
## Aligning Text
You can align paragraphs of text to the left, right, or center.
@@ -221,7 +281,15 @@ lipgloss.NewStyle().
Border(lipgloss.DoubleBorder(), true, false, false, true)
```
-For more on borders see [the docs][docs].
+You can also pass multiple colors to a border for a gradient effect:
+
+```go
+s := lipgloss.NewStyle().
+ Border(lipgloss.RoundedBorder()).
+ BorderForegroundBlend(lipgloss.Color("#FF0000"), lipgloss.Color("#0000FF"))
+```
+
+For more on borders see [the docs](https://pkg.go.dev/charm.land/lipgloss/v2#Border).
## Copying Styles
@@ -233,12 +301,10 @@ style := lipgloss.NewStyle().Foreground(lipgloss.Color("219"))
copiedStyle := style // this is a true copy
wildStyle := style.Blink(true) // this is also true copy, with blink added
-
```
-Since `Style` data structures contains only primitive types, assigning a style
-to another effectively creates a new copy of the style without mutating the
-original.
+Since `Style` is a pure value type, assigning a style to another effectively
+creates a new copy of the style without mutating the original.
## Inheritance
@@ -269,7 +335,7 @@ var style = lipgloss.NewStyle().
UnsetBackground() // never mind
```
-When a rule is unset, it won't be inherited or copied.
+When a rule is unset, it won’t be inherited or copied.
## Enforcing Rules
@@ -302,50 +368,57 @@ style = style.TabWidth(0) // remove tabs entirely
style = style.TabWidth(lipgloss.NoTabConversion) // leave tabs intact
```
+## Wrapping
+
+The `Wrap` function wraps text while preserving ANSI styles and hyperlinks
+across line boundaries:
+
+```go
+wrapped := lipgloss.Wrap(styledText, 40, " ")
+```
+
## Rendering
Generally, you just call the `Render(string...)` method on a `lipgloss.Style`:
```go
style := lipgloss.NewStyle().Bold(true).SetString("Hello,")
-fmt.Println(style.Render("kitty.")) // Hello, kitty.
-fmt.Println(style.Render("puppy.")) // Hello, puppy.
+lipgloss.Println(style.Render("kitty.")) // Hello, kitty.
+lipgloss.Println(style.Render("puppy.")) // Hello, puppy.
```
But you could also use the Stringer interface:
```go
var style = lipgloss.NewStyle().SetString("你好,猫咪。").Bold(true)
-fmt.Println(style) // 你好,猫咪。
+lipgloss.Println(style) // 你好,猫咪。
```
-### Custom Renderers
+## Utilities
-Custom renderers allow you to render to a specific outputs. This is
-particularly important when you want to render to different outputs and
-correctly detect the color profile and dark background status for each, such as
-in a server-client situation.
+In addition to pure styling, Lip Gloss also ships with some utilities to help
+assemble your layouts.
-```go
-func myLittleHandler(sess ssh.Session) {
- // Create a renderer for the client.
- renderer := lipgloss.NewRenderer(sess)
+### Compositing
- // Create a new style on the renderer.
- style := renderer.NewStyle().Background(lipgloss.AdaptiveColor{Light: "63", Dark: "228"})
+
- // Render. The color profile and dark background state will be correctly detected.
- io.WriteString(sess, style.Render("Heyyyyyyy"))
-}
-```
+Lip Gloss includes a powerful, cell-based compositor for rendering layered
+content:
-For an example on using a custom renderer over SSH with [Wish][wish] see the
-[SSH example][ssh-example].
+```go
+// Create some layers.
+a := lipgloss.NewLayer(pickles).X(4).Y(2).Z(1)
+b := lipgloss.NewLayer(bitterMelon).X(22).Y(1)
+c := lipgloss.NewLayer(sriracha).X(11).Y(7)
-## Utilities
+// Composite 'em and render.
+output := compositor.Compose(a, b, c).Render()
+```
-In addition to pure styling, Lip Gloss also ships with some utilities to help
-assemble your layouts.
+For a more thorough example, see [the canvas
+example](./examples/canvas/main.go). For reference, including how to detect
+mouse clicks on layers, see [the docs][docs].
### Joining Paragraphs
@@ -383,9 +456,22 @@ height := lipgloss.Height(block)
w, h := lipgloss.Size(block)
```
+### Blending Colors
+
+You can blend colors in one or two dimensions for gradient effects:
+
+```go
+// 1-dimentinoal gradient
+colors := lipgloss.Blend1D(10, lipgloss.Color("#FF0000"), lipgloss.Color("#0000FF"))
+
+// 2-dimensional gradient with rotation
+colors := lipgloss.Blend2D(80, 24, 45.0, color1, color2, color3)
+```
+
### Placing Text in Whitespace
-Sometimes you’ll simply want to place a block of text in whitespace.
+Sometimes you’ll simply want to place a block of text in whitespace. This is
+a lightweight alternative to compositing.
```go
// Center a paragraph horizontally in a space 80 cells wide. The height of
@@ -407,7 +493,7 @@ You can also style the whitespace. For details, see [the docs][docs].
Lip Gloss ships with a table rendering sub-package.
```go
-import "github.com/charmbracelet/lipgloss/table"
+import "charm.land/lipgloss/v2/table"
```
Define some rows of data.
@@ -459,14 +545,11 @@ t.Row("English", "You look absolutely fabulous.", "How's it going?")
Print the table.
```go
-fmt.Println(t)
+lipgloss.Println(t)
```

-> [!WARNING]
-> Table `Rows` need to be declared before `Offset` otherwise it does nothing.
-
### Table Borders
There are helpers to generate tables in markdown or ASCII style:
@@ -503,14 +586,14 @@ table.New().Border(lipgloss.ASCIIBorder())
+----------+--------------+-----------+
```
-For more on tables see [the docs](https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc) and [examples](https://github.com/charmbracelet/lipgloss/tree/master/examples/table).
+For more on tables see [the docs][docs] and [examples](https://github.com/charmbracelet/lipgloss/tree/master/examples/table).
## Rendering Lists
Lip Gloss ships with a list rendering sub-package.
```go
-import "github.com/charmbracelet/lipgloss/list"
+import "charm.land/lipgloss/v2/list"
```
Define a new list.
@@ -522,7 +605,7 @@ l := list.New("A", "B", "C")
Print the list.
```go
-fmt.Println(l)
+lipgloss.Println(l)
// • A
// • B
@@ -548,7 +631,7 @@ l := list.New(
Print the list.
```go
-fmt.Println(l)
+lipgloss.Println(l)
```
@@ -564,7 +647,7 @@ itemStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("212")).MarginRight(1
l := list.New(
"Glossier",
- "Claire’s Boutique",
+ "Claire's Boutique",
"Nyx",
"Mac",
"Milk",
@@ -617,7 +700,7 @@ for i := 0; i < repeat; i++ {
Lip Gloss ships with a tree rendering sub-package.
```go
-import "github.com/charmbracelet/lipgloss/tree"
+import "charm.land/lipgloss/v2/tree"
```
Define a new tree.
@@ -630,7 +713,7 @@ t := tree.Root(".").
Print the tree.
```go
-fmt.Println(t)
+lipgloss.Println(t)
// .
// ├── A
@@ -661,7 +744,7 @@ t := tree.Root(".").
Print the tree.
```go
-fmt.Println(t)
+lipgloss.Println(t)
```
@@ -713,49 +796,159 @@ for i := 0; i < repeat; i++ {
}
```
----
+## Advanced Color Usage
-## FAQ
+One of the most powerful features of Lip Gloss is the ability to render
+different colors at runtime depending on the user's terminal and environment,
+allowing you to present the best possible user experience.
-
-
-Why are things misaligning? Why are borders at the wrong widths?
-
-
This is most likely due to your locale and encoding, particularly with
-regard to Chinese, Japanese, and Korean (for example, zh_CN.UTF-8
-or ja_JP.UTF-8). The most direct way to fix this is to set
-RUNEWIDTH_EASTASIAN=0 in your environment.
-
+This section shows you how to do exactly that.
-
-Why isn't Lip Gloss displaying colors?
-
-
Lip Gloss automatically degrades colors to the best available option in the
-given terminal, and if output's not a TTY it will remove color output entirely.
-This is common when running tests, CI, or when piping output elsewhere.
+Migrating from v1?
-
If necessary, you can force a color profile in your tests with
-SetColorProfile.
+The `compat` package provides `AdaptiveColor`, `CompleteColor`, and
+`CompleteAdaptiveColor` for a quicker migration from v1. These work by
+looking at `stdin` and `stdout` on a global basis:
```go
-import (
- "github.com/charmbracelet/lipgloss"
- "github.com/muesli/termenv"
-)
+import "charm.land/lipgloss/v2/compat"
-lipgloss.SetColorProfile(termenv.TrueColor)
+color := compat.AdaptiveColor{
+ Light: lipgloss.Color("#f1f1f1"),
+ Dark: lipgloss.Color("#cccccc"),
+}
```
-_Note:_ this option limits the flexibility of your application and can cause
-ANSI escape codes to be output in cases where that might not be desired. Take
-careful note of your use case and environment before choosing to force a color
-profile.
+Note that we don't recommend this for new code as it removes the purity from
+Lip Gloss, computationally speaking, as it removes transparency around when
+I/O happens, which could cause Lip Gloss to compete for resources (like stdin)
+with other tools.
+### Adaptive Colors
+
+You can render different colors at runtime depending on whether the terminal
+has a light or dark background:
+
+```go
+hasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
+lightDark := lipgloss.LightDark(hasDarkBG)
+
+myColor := lightDark(lipgloss.Color("#D7FFAE"), lipgloss.Color("#D75FEE"))
+```
+
+#### With Bubble Tea
+
+In Bubble Tea, request the background color, listen for a
+`BackgroundColorMsg`, and respond accordingly:
+
+```go
+func (m model) Init() tea.Cmd {
+ // First, send a Cmd to request the terminal background color.
+ return tea.RequestBackgroundColor
+}
+
+func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
+ switch msg := msg.(type) {
+ case tea.BackgroundColorMsg:
+ // Great, we have the background color. Now we can set up our styles
+ // against the color.
+ m.styles = newStyles(msg.IsDark())
+ return m, nil
+ }
+}
+
+func newStyles(bgIsDark bool) styles {
+ // A little ternary function that will return the appropriate color
+ // based on the background color.
+ lightDark := lipgloss.LightDark(bgIsDark)
+
+ return styles{
+ myHotStyle: lipgloss.NewStyle().Foreground(lightDark(
+ lipgloss.Color("#f1f1f1"),
+ lipgloss.Color("#333333"),
+ )),
+ }
+}
+```
+
+#### Standalone
+
+If you’re not using Bubble Tea you can perform the query manually:
+
+```go
+// What's the background color?
+hasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stderr)
+
+// A helper function that will return the appropriate color based on the
+// background.
+lightDark := lipgloss.LightDark(hasDarkBG)
+
+// A couple colors with light and dark variants.
+thisColor := lightDark(lipgloss.Color("#C5ADF9"), lipgloss.Color("#864EFF"))
+thatColor := lightDark(lipgloss.Color("#37CD96"), lipgloss.Color("#22C78A"))
+
+a := lipgloss.NewStyle().Foreground(thisColor).Render("this")
+b := lipgloss.NewStyle().Foreground(thatColor).Render("that")
+
+// Render the appropriate colors at runtime:
+lipgloss.Fprintf(os.Stderr, "my fave colors are %s and %s", a, b)
+```
+
+### Complete Colors
+
+In some cases where you may want to specify exact values for each color profile
+(ANSI 16, ANSI 156, and TrueColor). For these cases, use the `Complete` helper:
+
+```go
+// You'll need the colorprofile package.
+import "github.com/charmbracelet/colorprofile"
+
+// Get the color profile.
+profile := colorprofile.Detect(os.Stdout, os.Environ())
+
+// Create a function for rendering the appropriate color based on the profile.
+var completeColor := lipgloss.Complete(profile)
+
+// Now we'll choose the appropriate color at runtime.
+myColor := completeColor(ansiColor, ansi256Color, trueColor)
+```
+
+### Color Downsampling
+
+One of the best things about Lip Gloss is that it can automatically downsample
+colors to the best available profile, stripping colors (and ANSI) entirely when
+output is not a TTY.
+
+If you’re using Lip Gloss with Bubble Tea there’s nothing to do here:
+downsampling is built into Bubble Tea v2. If you’re not using Bubble Tea, use
+the Lip Gloss writer functions, which are a drop-in replacement for the `fmt`
+package:
+
+```go
+s := lipgloss.NewStyle()
+ .Foreground(lipgloss.Color("#EB4268"))
+ .Render("Hello!")
+
+// Downsample if needed and print to stdout.
+lipgloss.Println(s)
+
+// Render to a variable.
+downsampled := lipgloss.Sprint(s)
+
+// Print to stderr.
+lipgloss.Fprint(os.Stderr, s)
+```
+
+The full set: `Print`, `Println`, `Printf`, `Fprint`, `Fprintln`, `Fprintf`,
+`Sprint`, `Sprintln`, `Sprintf`.
+
+Need more control? Check out
+[Colorprofile](https://github.com/charmbracelet/colorprofile), which Lip Gloss
+uses under the hood.
+
## What about [Bubble Tea][tea]?
Lip Gloss doesn’t replace Bubble Tea. Rather, it is an excellent Bubble Tea
@@ -765,16 +958,7 @@ instead of concerning yourself with low-level layout details.
In simple terms, you can use Lip Gloss to help build your Bubble Tea views.
-[tea]: https://github.com/charmbracelet/tea
-
-## Under the Hood
-
-Lip Gloss is built on the excellent [Termenv][termenv] and [Reflow][reflow]
-libraries which deal with color and ANSI-aware text operations, respectively.
-For many use cases Termenv and Reflow will be sufficient for your needs.
-
-[termenv]: https://github.com/muesli/termenv
-[reflow]: https://github.com/muesli/reflow
+[tea]: https://github.com/charmbracelet/bubbletea
## Rendering Markdown
@@ -794,9 +978,8 @@ See [contributing][contribute].
We’d love to hear your thoughts on this project. Feel free to drop us a note!
-- [Twitter](https://twitter.com/charmcli)
-- [The Fediverse](https://mastodon.social/@charmcli)
-- [Discord](https://charm.sh/chat)
+- [Discord](https://charm.land/chat)
+- [Matrix](https://charm.land/matrix)
## License
@@ -804,12 +987,10 @@ We’d love to hear your thoughts on this project. Feel free to drop us a note!
---
-Part of [Charm](https://charm.sh).
+Part of [Charm](https://charm.land).
-
+
Charm热爱开源 • Charm loves open source
-[docs]: https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc
-[wish]: https://github.com/charmbracelet/wish
-[ssh-example]: examples/ssh
+[docs]: https://pkg.go.dev/charm.land/lipgloss/v2?tab=doc
diff --git a/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml b/vendor/charm.land/lipgloss/v2/Taskfile.yaml
similarity index 72%
rename from vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml
rename to vendor/charm.land/lipgloss/v2/Taskfile.yaml
index 0b4a7711..84fcf6c6 100644
--- a/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml
+++ b/vendor/charm.land/lipgloss/v2/Taskfile.yaml
@@ -1,6 +1,6 @@
# https://taskfile.dev
-version: '3'
+version: "3"
tasks:
lint:
@@ -17,3 +17,8 @@ tasks:
desc: Run table tests
cmds:
- go test ./table {{.CLI_ARGS}}
+
+ test:tree:
+ desc: Run tree tests
+ cmds:
+ - go test ./tree {{.CLI_ARGS}}
diff --git a/vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md b/vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md
new file mode 100644
index 00000000..8f123f19
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md
@@ -0,0 +1,504 @@
+# Lip Gloss v2 Upgrade Guide
+
+This guide covers migrating from Lip Gloss v1 (`github.com/charmbracelet/lipgloss`)
+to Lip Gloss v2 (`charm.land/lipgloss/v2`). It is written for both humans and
+LLMs performing automated migrations.
+
+---
+
+## Table of Contents
+
+1. [Quick Start](#quick-start)
+2. [Module Path](#module-path)
+3. [Color System](#color-system)
+4. [Renderer Removal](#renderer-removal)
+5. [Printing and Color Downsampling](#printing-and-color-downsampling)
+6. [Background Detection and Adaptive Colors](#background-detection-and-adaptive-colors)
+7. [Whitespace Options](#whitespace-options)
+8. [Underline](#underline)
+9. [Style API Changes](#style-api-changes)
+10. [Tree Subpackage](#tree-subpackage)
+11. [Removed APIs](#removed-apis)
+12. [Quick Reference Table](#quick-reference-table)
+
+---
+
+## Quick Start
+
+For the fastest possible upgrade, do these two things:
+
+### 1. Use the `compat` package for adaptive/complete colors
+
+```go
+import "charm.land/lipgloss/v2/compat"
+
+// v1
+color := lipgloss.AdaptiveColor{Light: "#f1f1f1", Dark: "#cccccc"}
+
+// v2
+color := compat.AdaptiveColor{Light: lipgloss.Color("#f1f1f1"), Dark: lipgloss.Color("#cccccc")}
+```
+
+The `compat` package reads `stdin`/`stdout` globally, just like v1. To
+customize:
+
+```go
+import (
+ "charm.land/lipgloss/v2/compat"
+ "github.com/charmbracelet/colorprofile"
+)
+
+func init() {
+ compat.HasDarkBackground = lipgloss.HasDarkBackground(os.Stdin, os.Stderr)
+ compat.Profile = colorprofile.Detect(os.Stderr, os.Environ())
+}
+```
+
+### 2. Use Lip Gloss writers for output
+
+```go
+// v1
+fmt.Println(s)
+
+// v2
+lipgloss.Println(s)
+```
+
+This ensures colors are automatically downsampled. If you're using Bubble Tea
+v2, this step is unnecessary — Bubble Tea handles it for you.
+
+**That's the quick path.** Read on for the full migration details.
+
+---
+
+## Module Path
+
+The import path has changed.
+
+```go
+// v1
+import "github.com/charmbracelet/lipgloss"
+
+// v2
+import "charm.land/lipgloss/v2"
+```
+
+**Install:**
+
+```bash
+go get charm.land/lipgloss/v2
+```
+
+All subpackages follow the same pattern:
+
+```go
+// v1
+import "github.com/charmbracelet/lipgloss/table"
+import "github.com/charmbracelet/lipgloss/tree"
+import "github.com/charmbracelet/lipgloss/list"
+
+// v2
+import "charm.land/lipgloss/v2/table"
+import "charm.land/lipgloss/v2/tree"
+import "charm.land/lipgloss/v2/list"
+```
+
+**Search-and-replace pattern:**
+
+```
+github.com/charmbracelet/lipgloss → charm.land/lipgloss/v2
+```
+
+---
+
+## Color System
+
+This is the most significant API change.
+
+### `Color` is now a function, not a type
+
+```go
+// v1 — Color is a string type
+var c lipgloss.Color = "21"
+var c lipgloss.Color = "#ff00ff"
+
+// v2 — Color is a function returning color.Color
+var c color.Color = lipgloss.Color("21")
+var c color.Color = lipgloss.Color("#ff00ff")
+```
+
+The return type is `image/color.Color` (from the standard library).
+
+### `TerminalColor` interface is removed
+
+All methods that accepted `lipgloss.TerminalColor` now accept
+`image/color.Color`:
+
+```go
+// v1
+func (s Style) Foreground(c TerminalColor) Style
+func (s Style) Background(c TerminalColor) Style
+func (s Style) BorderForeground(c ...TerminalColor) Style
+
+// v2
+func (s Style) Foreground(c color.Color) Style
+func (s Style) Background(c color.Color) Style
+func (s Style) BorderForeground(c ...color.Color) Style
+```
+
+**Migration:** Replace every `lipgloss.TerminalColor` with `color.Color` and
+add `import "image/color"`.
+
+### `ANSIColor` is now an alias
+
+```go
+// v1 — custom uint type
+type ANSIColor uint
+
+// v2 — alias for ansi.IndexedColor
+type ANSIColor = ansi.IndexedColor
+```
+
+v2 also exports named constants for the 16 basic ANSI colors:
+
+```go
+lipgloss.Black, lipgloss.Red, lipgloss.Green, lipgloss.Yellow,
+lipgloss.Blue, lipgloss.Magenta, lipgloss.Cyan, lipgloss.White,
+lipgloss.BrightBlack, lipgloss.BrightRed, lipgloss.BrightGreen,
+lipgloss.BrightYellow, lipgloss.BrightBlue, lipgloss.BrightMagenta,
+lipgloss.BrightCyan, lipgloss.BrightWhite
+```
+
+### `AdaptiveColor`, `CompleteColor`, `CompleteAdaptiveColor`
+
+These types have been moved out of the root package. Use the `compat` package
+for a drop-in replacement, or use the new `LightDark` and `Complete` helpers
+for explicit control:
+
+```go
+// v1
+color := lipgloss.AdaptiveColor{Light: "#0000ff", Dark: "#000099"}
+
+// v2 — using compat (quick path)
+color := compat.AdaptiveColor{
+ Light: lipgloss.Color("#0000ff"),
+ Dark: lipgloss.Color("#000099"),
+}
+
+// v2 — using LightDark (recommended)
+hasDark := lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
+lightDark := lipgloss.LightDark(hasDark)
+color := lightDark(lipgloss.Color("#0000ff"), lipgloss.Color("#000099"))
+```
+
+```go
+// v1
+color := lipgloss.CompleteColor{TrueColor: "#ff00ff", ANSI256: "200", ANSI: "5"}
+
+// v2 — using compat
+color := compat.CompleteColor{
+ TrueColor: lipgloss.Color("#ff00ff"),
+ ANSI256: lipgloss.Color("200"),
+ ANSI: lipgloss.Color("5"),
+}
+
+// v2 — using Complete (recommended)
+profile := colorprofile.Detect(os.Stdout, os.Environ())
+complete := lipgloss.Complete(profile)
+color := complete(lipgloss.Color("5"), lipgloss.Color("200"), lipgloss.Color("#ff00ff"))
+```
+
+Note that `compat.AdaptiveColor` and friends take `color.Color` values for
+their fields, not strings.
+
+---
+
+## Renderer Removal
+
+The `Renderer` type and all associated functions are removed. In v1, every
+`Style` carried a `*Renderer` pointer and the package maintained a global
+default renderer.
+
+```go
+// v1 — these no longer exist
+lipgloss.DefaultRenderer()
+lipgloss.SetDefaultRenderer(r)
+lipgloss.NewRenderer(w, opts...)
+lipgloss.ColorProfile()
+lipgloss.SetColorProfile(p)
+renderer.NewStyle()
+```
+
+**In v2, `Style` is a plain value type.** There is no renderer. Color
+downsampling is handled at the output layer (see next section).
+
+**Migration:**
+
+- Replace `lipgloss.DefaultRenderer().NewStyle()` with `lipgloss.NewStyle()`.
+- Replace `renderer.NewStyle()` with `lipgloss.NewStyle()`.
+- Remove any `*Renderer` fields from your types.
+- Remove calls to `SetColorProfile` — use `colorprofile.Detect` at the output
+ layer instead.
+
+---
+
+## Printing and Color Downsampling
+
+In v1, color downsampling happened inside `Style.Render()` via the renderer. In
+v2, `Render()` always emits full-fidelity ANSI. Downsampling happens when you
+print.
+
+### Standalone Usage
+
+Use the Lip Gloss writer functions:
+
+```go
+s := someStyle.Render("Hello!")
+
+// Print to stdout with automatic downsampling
+lipgloss.Println(s)
+
+// Print to stderr
+lipgloss.Fprintln(os.Stderr, s)
+
+// Render to a string (downsampled for stdout's profile)
+str := lipgloss.Sprint(s)
+```
+
+The default writer targets `stdout`. To customize:
+
+```go
+lipgloss.Writer = colorprofile.NewWriter(os.Stderr, os.Environ())
+```
+
+### With Bubble Tea
+
+No changes needed. Bubble Tea v2 handles downsampling internally.
+
+---
+
+## Background Detection and Adaptive Colors
+
+### Standalone
+
+v1 detected the background color automatically via the global renderer. v2
+requires explicit queries:
+
+```go
+// v1
+hasDark := lipgloss.HasDarkBackground()
+
+// v2 — specify the input and output
+hasDark := lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
+```
+
+Then use `LightDark` to pick colors:
+
+```go
+lightDark := lipgloss.LightDark(hasDark)
+fg := lightDark(lipgloss.Color("#333333"), lipgloss.Color("#f1f1f1"))
+
+s := lipgloss.NewStyle().Foreground(fg)
+```
+
+### With Bubble Tea
+
+Request the background color in `Init` and listen for the response:
+
+```go
+func (m model) Init() tea.Cmd {
+ return tea.RequestBackgroundColor
+}
+
+func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
+ switch msg := msg.(type) {
+ case tea.BackgroundColorMsg:
+ m.styles = newStyles(msg.IsDark())
+ }
+ // ...
+}
+
+func newStyles(bgIsDark bool) styles {
+ lightDark := lipgloss.LightDark(bgIsDark)
+ return styles{
+ title: lipgloss.NewStyle().Foreground(lightDark(
+ lipgloss.Color("#333333"),
+ lipgloss.Color("#f1f1f1"),
+ )),
+ }
+}
+```
+
+---
+
+## Whitespace Options
+
+The separate foreground/background whitespace options have been replaced by a
+single style option:
+
+```go
+// v1
+lipgloss.Place(width, height, hPos, vPos, str,
+ lipgloss.WithWhitespaceForeground(lipgloss.Color("#333")),
+ lipgloss.WithWhitespaceBackground(lipgloss.Color("#000")),
+)
+
+// v2
+lipgloss.Place(width, height, hPos, vPos, str,
+ lipgloss.WithWhitespaceStyle(lipgloss.NewStyle().
+ Foreground(lipgloss.Color("#333")).
+ Background(lipgloss.Color("#000")),
+ ),
+)
+```
+
+---
+
+## Underline
+
+`Underline(bool)` still works for basic on/off. v2 adds fine-grained control:
+
+```go
+// v1
+s := lipgloss.NewStyle().Underline(true)
+
+// v2 — still works
+s := lipgloss.NewStyle().Underline(true)
+
+// v2 — new: specific styles
+s := lipgloss.NewStyle().UnderlineStyle(lipgloss.UnderlineCurly)
+
+// v2 — new: colored underlines
+s := lipgloss.NewStyle().
+ UnderlineStyle(lipgloss.UnderlineSingle).
+ UnderlineColor(lipgloss.Color("#FF0000"))
+```
+
+Internally, `Underline(true)` is equivalent to `UnderlineStyle(UnderlineSingle)`
+and `Underline(false)` is equivalent to `UnderlineStyle(UnderlineNone)`.
+
+---
+
+## Style API Changes
+
+### `NewStyle()` is no longer tied to a Renderer
+
+```go
+// v1
+s := lipgloss.NewStyle() // uses global renderer
+s := renderer.NewStyle() // uses specific renderer
+
+// v2
+s := lipgloss.NewStyle() // pure value, no renderer
+```
+
+### Color getters return `color.Color`
+
+```go
+// v1
+fg := s.GetForeground() // returns TerminalColor
+
+// v2
+fg := s.GetForeground() // returns color.Color
+```
+
+### New style methods
+
+| Method | Description |
+|---|---|
+| `UnderlineStyle(Underline)` | Set underline style (single, double, curly, etc.) |
+| `UnderlineColor(color.Color)` | Set underline color |
+| `PaddingChar(rune)` | Set the character used for padding fill |
+| `MarginChar(rune)` | Set the character used for margin fill |
+| `Hyperlink(link, params...)` | Set a clickable hyperlink |
+| `BorderForegroundBlend(...color.Color)` | Apply gradient colors to borders |
+| `BorderForegroundBlendOffset(int)` | Set the offset for border gradient |
+
+Each has a corresponding `Get*`, `Unset*`, and where applicable `Get*`
+accessor.
+
+---
+
+## Tree Subpackage
+
+The import path changes and there are new styling options:
+
+```go
+// v1
+import "github.com/charmbracelet/lipgloss/tree"
+
+// v2
+import "charm.land/lipgloss/v2/tree"
+```
+
+New methods:
+
+- `IndenterStyle(lipgloss.Style)` — set a static style for tree indentation.
+- `IndenterStyleFunc(func(Children, int) lipgloss.Style)` — conditionally style
+ indentation.
+- `Width(int)` — set tree width for padding.
+
+---
+
+## Removed APIs
+
+The following types and functions no longer exist in v2. This table shows each
+removed symbol and its replacement.
+
+| v1 Symbol | v2 Replacement |
+|---|---|
+| `type Renderer` | Removed entirely |
+| `DefaultRenderer()` | Not needed |
+| `SetDefaultRenderer(r)` | Not needed |
+| `NewRenderer(w, opts...)` | Not needed |
+| `ColorProfile()` | `colorprofile.Detect(w, env)` |
+| `SetColorProfile(p)` | Set `lipgloss.Writer.Profile` |
+| `HasDarkBackground()` (no args) | `lipgloss.HasDarkBackground(in, out)` |
+| `SetHasDarkBackground(b)` | Not needed — pass bool to `LightDark` |
+| `type TerminalColor` | `image/color.Color` |
+| `type Color string` | `func Color(string) color.Color` |
+| `type ANSIColor uint` | `type ANSIColor = ansi.IndexedColor` |
+| `type AdaptiveColor` | `compat.AdaptiveColor` or `LightDark` |
+| `type CompleteColor` | `compat.CompleteColor` or `Complete` |
+| `type CompleteAdaptiveColor` | `compat.CompleteAdaptiveColor` |
+| `WithWhitespaceForeground(c)` | `WithWhitespaceStyle(s)` |
+| `WithWhitespaceBackground(c)` | `WithWhitespaceStyle(s)` |
+| `renderer.NewStyle()` | `lipgloss.NewStyle()` |
+
+---
+
+## Quick Reference Table
+
+A side-by-side summary for common patterns:
+
+| Task | v1 | v2 |
+|---|---|---|
+| Import | `"github.com/charmbracelet/lipgloss"` | `"charm.land/lipgloss/v2"` |
+| Create style | `lipgloss.NewStyle()` | `lipgloss.NewStyle()` |
+| Hex color | `lipgloss.Color("#ff00ff")` | `lipgloss.Color("#ff00ff")` |
+| ANSI color | `lipgloss.Color("5")` | `lipgloss.Color("5")` or `lipgloss.Magenta` |
+| Adaptive color | `lipgloss.AdaptiveColor{Light: "#fff", Dark: "#000"}` | `compat.AdaptiveColor{Light: lipgloss.Color("#fff"), Dark: lipgloss.Color("#000")}` |
+| Set foreground | `s.Foreground(lipgloss.Color("5"))` | `s.Foreground(lipgloss.Color("5"))` |
+| Print with downsampling | `fmt.Println(s.Render("hi"))` | `lipgloss.Println(s.Render("hi"))` |
+| Detect dark bg | `lipgloss.HasDarkBackground()` | `lipgloss.HasDarkBackground(os.Stdin, os.Stdout)` |
+| Light/dark color | `lipgloss.AdaptiveColor{...}` | `lipgloss.LightDark(isDark)(light, dark)` |
+| Whitespace styling | `WithWhitespaceForeground(c)` | `WithWhitespaceStyle(lipgloss.NewStyle().Foreground(c))` |
+| Underline | `s.Underline(true)` | `s.Underline(true)` or `s.UnderlineStyle(lipgloss.UnderlineCurly)` |
+
+---
+
+## Feedback
+
+Questions, issues, or feedback:
+
+- [Discord](https://charm.land/discord)
+- [Matrix](https://charm.land/matrix)
+- [Email](mailto:vt100@charm.land)
+
+---
+
+Part of [Charm](https://charm.land).
+
+
+
+Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة
diff --git a/vendor/github.com/charmbracelet/lipgloss/align.go b/vendor/charm.land/lipgloss/v2/align.go
similarity index 89%
rename from vendor/github.com/charmbracelet/lipgloss/align.go
rename to vendor/charm.land/lipgloss/v2/align.go
index ce654b23..d196213b 100644
--- a/vendor/github.com/charmbracelet/lipgloss/align.go
+++ b/vendor/charm.land/lipgloss/v2/align.go
@@ -4,13 +4,12 @@ import (
"strings"
"github.com/charmbracelet/x/ansi"
- "github.com/muesli/termenv"
)
// Perform text alignment. If the string is multi-lined, we also make all lines
-// the same width by padding them with spaces. If a termenv style is passed,
-// use that to style the spaces added.
-func alignTextHorizontal(str string, pos Position, width int, style *termenv.Style) string {
+// the same width by padding them with spaces. If a style is passed, use that
+// to style the spaces added.
+func alignTextHorizontal(str string, pos Position, width int, style *ansi.Style) string {
lines, widestLine := getLines(str)
var b strings.Builder
@@ -21,7 +20,7 @@ func alignTextHorizontal(str string, pos Position, width int, style *termenv.Sty
shortAmount += max(0, width-(shortAmount+lineWidth)) // difference from the total width, if set
if shortAmount > 0 {
- switch pos { //nolint:exhaustive
+ switch pos {
case Right:
s := strings.Repeat(" ", shortAmount)
if style != nil {
@@ -59,7 +58,7 @@ func alignTextHorizontal(str string, pos Position, width int, style *termenv.Sty
return b.String()
}
-func alignTextVertical(str string, pos Position, height int, _ *termenv.Style) string {
+func alignTextVertical(str string, pos Position, height int, _ *ansi.Style) string {
strHeight := strings.Count(str, "\n") + 1
if height < strHeight {
return str
diff --git a/vendor/charm.land/lipgloss/v2/ansi_unix.go b/vendor/charm.land/lipgloss/v2/ansi_unix.go
new file mode 100644
index 00000000..b4fca7d1
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/ansi_unix.go
@@ -0,0 +1,8 @@
+//go:build !windows
+
+package lipgloss
+
+import "os"
+
+// EnableLegacyWindowsANSI is only needed on Windows.
+func EnableLegacyWindowsANSI(*os.File) {}
diff --git a/vendor/charm.land/lipgloss/v2/ansi_windows.go b/vendor/charm.land/lipgloss/v2/ansi_windows.go
new file mode 100644
index 00000000..8a1ef00e
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/ansi_windows.go
@@ -0,0 +1,30 @@
+//go:build windows
+
+package lipgloss
+
+import (
+ "os"
+
+ "golang.org/x/sys/windows"
+)
+
+// EnableLegacyWindowsANSI enables support for ANSI color sequences in the
+// Windows default console (cmd.exe and the PowerShell application). Note that
+// this only works with Windows 10 and greater. Also note that Windows Terminal
+// supports colors by default.
+func EnableLegacyWindowsANSI(f *os.File) {
+ var mode uint32
+ handle := windows.Handle(f.Fd())
+ err := windows.GetConsoleMode(handle, &mode)
+ if err != nil {
+ return
+ }
+
+ // See https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
+ if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
+ vtpmode := mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
+ if err := windows.SetConsoleMode(handle, vtpmode); err != nil {
+ return
+ }
+ }
+}
diff --git a/vendor/charm.land/lipgloss/v2/blending.go b/vendor/charm.land/lipgloss/v2/blending.go
new file mode 100644
index 00000000..82830f3e
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/blending.go
@@ -0,0 +1,196 @@
+package lipgloss
+
+import (
+ "image/color"
+ "math"
+ "slices"
+
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+// Blend1D blends a series of colors together in one linear dimension using multiple
+// stops, into the provided number of steps. Uses the "CIE L*, a*, b*" (CIELAB) color-space.
+//
+// Note that if any of the provided colors are completely transparent, we will
+// assume that the alpha value was lost in conversion from RGB -> RGBA, and we
+// will set the alpha to opaque, as it's not possible to blend something completely
+// transparent.
+func Blend1D(steps int, stops ...color.Color) []color.Color {
+ if steps < 0 {
+ steps = 0
+ }
+
+ if steps <= len(stops) {
+ return stops[:steps]
+ }
+
+ // Ensure they didn't provide any nil colors.
+ stops = slices.DeleteFunc(stops, func(c color.Color) bool {
+ return c == nil
+ })
+
+ if len(stops) == 0 {
+ return nil // We can't safely fallback.
+ }
+
+ // If they only provided one valid color (or some nil colors), we will just return
+ // an array of that color, for the amount of steps they requested.
+ if len(stops) == 1 {
+ singleColor := stops[0]
+ result := make([]color.Color, steps)
+ for i := range result {
+ result[i] = singleColor
+ }
+ return result
+ }
+
+ blended := make([]color.Color, steps)
+
+ // Convert stops to colorful.Color once
+ cstops := make([]colorful.Color, len(stops))
+ for i, k := range stops {
+ cstops[i], _ = colorful.MakeColor(ensureNotTransparent(k))
+ }
+
+ numSegments := len(cstops) - 1
+ defaultSize := steps / numSegments
+ remainingSteps := steps % numSegments
+
+ resultIndex := 0
+ for i := range numSegments {
+ from := cstops[i]
+ to := cstops[i+1]
+
+ // Calculate segment size.
+ segmentSize := defaultSize
+ if i < remainingSteps {
+ segmentSize++
+ }
+
+ divisor := float64(segmentSize - 1)
+
+ // Generate colors for this segment.
+ for j := 0; j < segmentSize; j++ {
+ var blendingFactor float64
+ if segmentSize > 1 {
+ blendingFactor = float64(j) / divisor
+ }
+ blended[resultIndex] = from.BlendLab(to, blendingFactor).Clamped()
+ resultIndex++
+ }
+ }
+
+ return blended
+}
+
+// Blend2D blends a series of colors together in two linear dimensions using
+// multiple stops, into the provided width/height. Uses the "CIE L*, a*, b*" (CIELAB)
+// color-space. The angle parameter controls the rotation of the gradient (0-360°),
+// where 0° is left-to-right, 45° is bottom-left to top-right (diagonal). The function
+// returns colors in a 1D row-major order ([row1, row2, row3, ...]).
+//
+// Example of how to iterate over the result:
+//
+// gradient := colors.Blend2D(width, height, 180, color1, color2, color3, ...)
+// gradientContent := strings.Builder{}
+// for y := range height {
+// for x := range width {
+// index := y*width + x
+// gradientContent.WriteString(
+// lipgloss.NewStyle().
+// Background(gradient[index]).
+// Render(" "),
+// )
+// }
+// if y < height-1 { // End of row.
+// gradientContent.WriteString("\n")
+// }
+// }
+//
+// Note that if any of the provided colors are completely transparent, we will
+// assume that the alpha value was lost in conversion from RGB -> RGBA, and we
+// will set the alpha to opaque, as it's not possible to blend something completely
+// transparent.
+func Blend2D(width, height int, angle float64, stops ...color.Color) []color.Color {
+ if width < 1 {
+ width = 1
+ }
+ if height < 1 {
+ height = 1
+ }
+
+ // Normalize angle to 0-360.
+ angle = math.Mod(angle, 360)
+ if angle < 0 {
+ angle += 360
+ }
+
+ // Ensure they didn't provide any nil colors.
+ stops = slices.DeleteFunc(stops, func(c color.Color) bool {
+ return c == nil
+ })
+
+ if len(stops) == 0 {
+ return nil // We can't safely fallback.
+ }
+
+ // If they only provided one valid color (or some nil colors), we will just return
+ // an array of that color, for the amount of pixels they requested.
+ if len(stops) == 1 {
+ singleColor := stops[0]
+ result := make([]color.Color, width*height)
+ for i := range result {
+ result[i] = singleColor
+ }
+ return result
+ }
+
+ // For 2D blending, we'll create a gradient along the diagonal and then sample
+ // from it based on the angle. We'll use the maximum dimension to ensure we have
+ // enough resolution for the gradient.
+ diagonalGradient := Blend1D(max(width, height), stops...)
+
+ result := make([]color.Color, width*height)
+
+ // Calculate center point for rotation.
+ centerX := float64(width-1) / 2.0
+ centerY := float64(height-1) / 2.0
+
+ angleRad := angle * math.Pi / 180.0 // -> radians.
+
+ // Pre-calculate sin and cos.
+ cosAngle := math.Cos(angleRad)
+ sinAngle := math.Sin(angleRad)
+
+ // Calculate diagonal length for proper gradient mapping.
+ diagonalLength := math.Sqrt(float64(width*width + height*height))
+
+ // Pre-calculate gradient length for index calculation.
+ gradientLen := float64(len(diagonalGradient) - 1)
+
+ for y := range height {
+ // Calculate the distance from center along the gradient direction.
+ dy := float64(y) - centerY
+
+ for x := 0; x < width; x++ {
+ // Calculate the distance from center along the gradient direction.
+ dx := float64(x) - centerX
+
+ rotX := dx*cosAngle - dy*sinAngle // Rotate the point by the angle.
+
+ // Map the rotated position to the gradient. Normalize to 0-1 range based on
+ // the diagonal length.
+ gradientPos := clamp((rotX+diagonalLength/2.0)/diagonalLength, 0, 1)
+
+ // Calculate the index in the gradient.
+ gradientIndex := int(gradientPos * gradientLen)
+ if gradientIndex >= len(diagonalGradient) {
+ gradientIndex = len(diagonalGradient) - 1
+ }
+
+ result[y*width+x] = diagonalGradient[gradientIndex] // -> row-major order.
+ }
+ }
+
+ return result
+}
diff --git a/vendor/github.com/charmbracelet/lipgloss/borders.go b/vendor/charm.land/lipgloss/v2/borders.go
similarity index 73%
rename from vendor/github.com/charmbracelet/lipgloss/borders.go
rename to vendor/charm.land/lipgloss/v2/borders.go
index b36f8743..7f12360f 100644
--- a/vendor/github.com/charmbracelet/lipgloss/borders.go
+++ b/vendor/charm.land/lipgloss/v2/borders.go
@@ -1,10 +1,13 @@
package lipgloss
import (
+ "image/color"
+ "slices"
"strings"
+ "unicode/utf8"
"github.com/charmbracelet/x/ansi"
- "github.com/muesli/termenv"
+ "github.com/clipperhouse/displaywidth"
"github.com/rivo/uniseg"
)
@@ -56,10 +59,7 @@ func (b Border) GetLeftSize() int {
func getBorderEdgeWidth(borderParts ...string) (maxWidth int) {
for _, piece := range borderParts {
- w := maxRuneWidth(piece)
- if w > maxWidth {
- maxWidth = w
- }
+ maxWidth = max(maxWidth, maxRuneWidth(piece))
}
return maxWidth
}
@@ -278,6 +278,52 @@ func ASCIIBorder() Border {
return asciiBorder
}
+type borderBlend struct {
+ topGradient []color.Color
+ rightGradient []color.Color
+ bottomGradient []color.Color
+ leftGradient []color.Color
+}
+
+func (s Style) borderBlend(width, height int, colors ...color.Color) *borderBlend {
+ gradient := Blend1D(
+ (height+width+2)*2,
+ colors...,
+ )
+
+ // Rotate array forward or reverse based on the offset if provided.
+ if r := -s.getAsInt(borderForegroundBlendOffsetKey); r != 0 {
+ n := len(gradient)
+ r %= n
+ if r < 0 {
+ r += n
+ }
+ slices.Reverse(gradient[:r])
+ slices.Reverse(gradient[r:])
+ slices.Reverse(gradient)
+ }
+
+ offset := 0
+ getFromOffset := func(size int) (s []color.Color) {
+ s = gradient[offset : offset+size]
+ offset += size
+ return s
+ }
+
+ blend := &borderBlend{
+ topGradient: getFromOffset(width + 2),
+ rightGradient: getFromOffset(height),
+ bottomGradient: getFromOffset(width + 2),
+ leftGradient: getFromOffset(height),
+ }
+
+ // bottom and left gradients are reversed because they are drawn in reverse order.
+ slices.Reverse(blend.bottomGradient)
+ slices.Reverse(blend.leftGradient)
+
+ return blend
+}
+
func (s Style) applyBorder(str string) string {
var (
border = s.getBorderStyle()
@@ -285,21 +331,11 @@ func (s Style) applyBorder(str string) string {
hasRight = s.getAsBool(borderRightKey, false)
hasBottom = s.getAsBool(borderBottomKey, false)
hasLeft = s.getAsBool(borderLeftKey, false)
-
- topFG = s.getAsColor(borderTopForegroundKey)
- rightFG = s.getAsColor(borderRightForegroundKey)
- bottomFG = s.getAsColor(borderBottomForegroundKey)
- leftFG = s.getAsColor(borderLeftForegroundKey)
-
- topBG = s.getAsColor(borderTopBackgroundKey)
- rightBG = s.getAsColor(borderRightBackgroundKey)
- bottomBG = s.getAsColor(borderBottomBackgroundKey)
- leftBG = s.getAsColor(borderLeftBackgroundKey)
)
// If a border is set and no sides have been specifically turned on or off
// render borders on all sides.
- if s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
hasTop = true
hasRight = true
hasBottom = true
@@ -320,8 +356,11 @@ func (s Style) applyBorder(str string) string {
width += maxRuneWidth(border.Left)
}
- if hasRight && border.Right == "" {
- border.Right = " "
+ if hasRight {
+ if border.Right == "" {
+ border.Right = " "
+ }
+ width += maxRuneWidth(border.Right)
}
// If corners should be rendered but are set with the empty string, fill them
@@ -370,13 +409,35 @@ func (s Style) applyBorder(str string) string {
border.BottomRight = getFirstRuneAsString(border.BottomRight)
border.BottomLeft = getFirstRuneAsString(border.BottomLeft)
+ var topFG, rightFG, bottomFG, leftFG color.Color
+ var (
+ blendFG = s.getAsColors(borderForegroundBlendKey)
+ topBG = s.getAsColor(borderTopBackgroundKey)
+ rightBG = s.getAsColor(borderRightBackgroundKey)
+ bottomBG = s.getAsColor(borderBottomBackgroundKey)
+ leftBG = s.getAsColor(borderLeftBackgroundKey)
+ )
+
+ var blend *borderBlend
+ if len(blendFG) > 0 {
+ blend = s.borderBlend(width, len(lines), blendFG...)
+ } else {
+ topFG = s.getAsColor(borderTopForegroundKey)
+ rightFG = s.getAsColor(borderRightForegroundKey)
+ bottomFG = s.getAsColor(borderBottomForegroundKey)
+ leftFG = s.getAsColor(borderLeftForegroundKey)
+ }
+
var out strings.Builder
// Render top
if hasTop {
top := renderHorizontalEdge(border.TopLeft, border.Top, border.TopRight, width)
- top = s.styleBorder(top, topFG, topBG)
- out.WriteString(top)
+ if blend != nil {
+ out.WriteString(s.styleBorderBlend(top, blend.topGradient, topBG))
+ } else {
+ out.WriteString(s.styleBorder(top, topFG, topBG))
+ }
out.WriteRune('\n')
}
@@ -387,23 +448,32 @@ func (s Style) applyBorder(str string) string {
rightIndex := 0
// Render sides
+ var r string
for i, l := range lines {
if hasLeft {
- r := string(leftRunes[leftIndex])
+ r = string(leftRunes[leftIndex])
leftIndex++
if leftIndex >= len(leftRunes) {
leftIndex = 0
}
- out.WriteString(s.styleBorder(r, leftFG, leftBG))
+ if blend != nil {
+ out.WriteString(s.styleBorder(r, blend.leftGradient[i], leftBG))
+ } else {
+ out.WriteString(s.styleBorder(r, leftFG, leftBG))
+ }
}
out.WriteString(l)
if hasRight {
- r := string(rightRunes[rightIndex])
+ r = string(rightRunes[rightIndex])
rightIndex++
if rightIndex >= len(rightRunes) {
rightIndex = 0
}
- out.WriteString(s.styleBorder(r, rightFG, rightBG))
+ if blend != nil {
+ out.WriteString(s.styleBorder(r, blend.rightGradient[i], rightBG))
+ } else {
+ out.WriteString(s.styleBorder(r, rightFG, rightBG))
+ }
}
if i < len(lines)-1 {
out.WriteRune('\n')
@@ -413,9 +483,12 @@ func (s Style) applyBorder(str string) string {
// Render bottom
if hasBottom {
bottom := renderHorizontalEdge(border.BottomLeft, border.Bottom, border.BottomRight, width)
- bottom = s.styleBorder(bottom, bottomFG, bottomBG)
out.WriteRune('\n')
- out.WriteString(bottom)
+ if blend != nil {
+ out.WriteString(s.styleBorderBlend(bottom, blend.bottomGradient, bottomBG))
+ } else {
+ out.WriteString(s.styleBorder(bottom, bottomFG, bottomBG))
+ }
}
return out.String()
@@ -435,49 +508,73 @@ func renderHorizontalEdge(left, middle, right string, width int) string {
out := strings.Builder{}
out.WriteString(left)
- for i := leftWidth + rightWidth; i < width+rightWidth; {
- out.WriteRune(runes[j])
+
+ for i := 0; i < width-leftWidth-rightWidth; {
+ r := runes[j]
+ out.WriteRune(r)
+ i += ansi.StringWidth(string(r))
j++
if j >= len(runes) {
j = 0
}
- i += ansi.StringWidth(string(runes[j]))
}
- out.WriteString(right)
+ out.WriteString(right)
return out.String()
}
-// Apply foreground and background styling to a border.
-func (s Style) styleBorder(border string, fg, bg TerminalColor) string {
+// styleBorder applies foreground and background styling to a border.
+func (s Style) styleBorder(border string, fg, bg color.Color) string {
if fg == noColor && bg == noColor {
return border
}
-
- style := termenv.Style{}
-
+ var style ansi.Style
if fg != noColor {
- style = style.Foreground(fg.color(s.r))
+ style = style.ForegroundColor(fg)
}
if bg != noColor {
- style = style.Background(bg.color(s.r))
+ style = style.BackgroundColor(bg)
}
-
return style.Styled(border)
}
+// styleBorderBlend applies foreground and background styling to a border, using blending.
+func (s Style) styleBorderBlend(border string, fg []color.Color, bg color.Color) string {
+ var out strings.Builder
+ var style ansi.Style
+ var i int
+
+ gr := uniseg.NewGraphemes(border)
+ for gr.Next() {
+ style = style[:0]
+ if fg[i] != noColor {
+ style = style.ForegroundColor(fg[i])
+ }
+ if bg != noColor {
+ style = style.BackgroundColor(bg)
+ }
+ _, _ = out.WriteString(style.String())
+ _, _ = out.Write(gr.Bytes())
+ i++
+ }
+ _, _ = out.WriteString(ansi.ResetStyle)
+ return out.String()
+}
+
func maxRuneWidth(str string) int {
+ switch len(str) {
+ case 0:
+ return 0
+ case 1:
+ return displaywidth.String(str)
+ }
+
var width int
- state := -1
- for len(str) > 0 {
- var w int
- _, str, w, state = uniseg.FirstGraphemeClusterInString(str, state)
- if w > width {
- width = w
- }
+ g := displaywidth.StringGraphemes(str)
+ for g.Next() {
+ width = max(width, g.Width())
}
-
return width
}
@@ -485,6 +582,6 @@ func getFirstRuneAsString(str string) string {
if str == "" {
return str
}
- r := []rune(str)
- return string(r[0])
+ _, size := utf8.DecodeRuneInString(str)
+ return str[:size]
}
diff --git a/vendor/charm.land/lipgloss/v2/canvas.go b/vendor/charm.land/lipgloss/v2/canvas.go
new file mode 100644
index 00000000..e6cc3b45
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/canvas.go
@@ -0,0 +1,89 @@
+package lipgloss
+
+import (
+ uv "github.com/charmbracelet/ultraviolet"
+ "github.com/charmbracelet/x/ansi"
+)
+
+// Canvas is a cell-buffer that can be used to compose and draw [uv.Drawable]s
+// like [Layer]s.
+//
+// Composed drawables are drawn onto the canvas in the order they were
+// composed, meaning later drawables will appear "on top" of earlier ones.
+//
+// A canvas can read, modify, and render its cell contents.
+//
+// It implements [uv.Screen] and [uv.Drawable].
+type Canvas struct {
+ scr uv.ScreenBuffer
+}
+
+var _ uv.Screen = (*Canvas)(nil)
+
+// NewCanvas creates a new [Canvas] with the given size.
+func NewCanvas(width, height int) *Canvas {
+ c := new(Canvas)
+ c.scr = uv.NewScreenBuffer(width, height)
+ c.scr.Method = ansi.GraphemeWidth
+ return c
+}
+
+// Resize resizes the canvas to the given width and height.
+func (c *Canvas) Resize(width, height int) {
+ c.scr.Resize(width, height)
+}
+
+// Clear clears the canvas.
+func (c *Canvas) Clear() {
+ c.scr.Clear()
+}
+
+// Bounds implements [uv.Screen].
+func (c *Canvas) Bounds() uv.Rectangle {
+ return c.scr.Bounds()
+}
+
+// Width returns the width of the canvas.
+func (c *Canvas) Width() int {
+ return c.scr.Width()
+}
+
+// Height returns the height of the canvas.
+func (c *Canvas) Height() int {
+ return c.scr.Height()
+}
+
+// CellAt implements [uv.Screen].
+func (c *Canvas) CellAt(x int, y int) *uv.Cell {
+ return c.scr.CellAt(x, y)
+}
+
+// SetCell implements [uv.Screen].
+func (c *Canvas) SetCell(x int, y int, cell *uv.Cell) {
+ c.scr.SetCell(x, y, cell)
+}
+
+// WidthMethod implements [uv.Screen].
+func (c *Canvas) WidthMethod() uv.WidthMethod {
+ return c.scr.WidthMethod()
+}
+
+// Compose composes a [Layer] or any [uv.Drawable] onto the [Canvas].
+func (c *Canvas) Compose(drawer uv.Drawable) *Canvas {
+ drawer.Draw(c, c.Bounds())
+ return c
+}
+
+// Draw draws the [Canvas] onto the given [uv.Screen] within the specified
+// area.
+//
+// It implements [uv.Drawable].
+func (c *Canvas) Draw(scr uv.Screen, area uv.Rectangle) {
+ c.scr.Draw(scr, area)
+}
+
+// Render renders the canvas into a styled string. Any trailing spaces are
+// trimmed.
+func (c *Canvas) Render() string {
+ return uv.TrimSpace(c.scr.Render())
+}
diff --git a/vendor/charm.land/lipgloss/v2/color.go b/vendor/charm.land/lipgloss/v2/color.go
new file mode 100644
index 00000000..7443dc10
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/color.go
@@ -0,0 +1,359 @@
+package lipgloss
+
+import (
+ "cmp"
+ "errors"
+ "image/color"
+ "strconv"
+ "strings"
+
+ "github.com/charmbracelet/colorprofile"
+ "github.com/charmbracelet/x/ansi"
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+func clamp[T cmp.Ordered](v, low, high T) T {
+ if high < low {
+ high, low = low, high
+ }
+ return min(high, max(low, v))
+}
+
+// 4-bit color constants.
+const (
+ Black ansi.BasicColor = iota
+ Red
+ Green
+ Yellow
+ Blue
+ Magenta
+ Cyan
+ White
+
+ BrightBlack
+ BrightRed
+ BrightGreen
+ BrightYellow
+ BrightBlue
+ BrightMagenta
+ BrightCyan
+ BrightWhite
+)
+
+var noColor = NoColor{}
+
+// NoColor is used to specify the absence of color styling. When this is active
+// foreground colors will be rendered with the terminal's default text color,
+// and background colors will not be drawn at all.
+//
+// Example usage:
+//
+// var style = someStyle.Background(lipgloss.NoColor{})
+type NoColor struct{}
+
+// RGBA returns the RGBA value of this color. Because we have to return
+// something, despite this color being the absence of color, we're returning
+// black with 100% opacity.
+//
+// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF.
+func (n NoColor) RGBA() (r, g, b, a uint32) {
+ return 0x0, 0x0, 0x0, 0xFFFF //nolint:mnd
+}
+
+// Color specifies a color by hex or ANSI256 value. For example:
+//
+// ansiColor := lipgloss.Color("1") // The same as lipgloss.Red
+// ansi256Color := lipgloss.Color("21")
+// hexColor := lipgloss.Color("#0000ff")
+func Color(s string) color.Color {
+ if strings.HasPrefix(s, "#") {
+ c, err := parseHex(s)
+ if err != nil {
+ return noColor
+ }
+ return c
+ }
+
+ i, err := strconv.Atoi(s)
+ if err != nil {
+ return noColor
+ }
+
+ if i < 0 {
+ // Only positive numbers
+ i = -i
+ }
+
+ if i < 16 {
+ return ansi.BasicColor(i) //nolint:gosec
+ } else if i < 256 {
+ return ANSIColor(i) //nolint:gosec
+ }
+
+ r, g, b := uint8((i>>16)&0xff), uint8(i>>8&0xff), uint8(i&0xff) //nolint:gosec
+ return color.RGBA{R: r, G: g, B: b, A: 0xff}
+}
+
+var errInvalidFormat = errors.New("invalid hex format") // pre-allocated.
+
+// parseHex parses a hex color string and returns a color.RGBA. The string can be
+// in the format #RRGGBB or #RGB. This is a more performant implementation of
+// [colorful.Hex].
+func parseHex(s string) (c color.RGBA, err error) {
+ c.A = 0xff
+
+ if len(s) == 0 || s[0] != '#' {
+ return c, errInvalidFormat
+ }
+
+ hexToByte := func(b byte) byte {
+ switch {
+ case b >= '0' && b <= '9':
+ return b - '0'
+ case b >= 'a' && b <= 'f':
+ return b - 'a' + 10
+ case b >= 'A' && b <= 'F':
+ return b - 'A' + 10
+ }
+ err = errInvalidFormat
+ return 0
+ }
+
+ switch len(s) {
+ case 7:
+ c.R = hexToByte(s[1])<<4 + hexToByte(s[2])
+ c.G = hexToByte(s[3])<<4 + hexToByte(s[4])
+ c.B = hexToByte(s[5])<<4 + hexToByte(s[6])
+ case 4:
+ c.R = hexToByte(s[1]) * 17
+ c.G = hexToByte(s[2]) * 17
+ c.B = hexToByte(s[3]) * 17
+ default:
+ err = errInvalidFormat
+ }
+ return c, err
+}
+
+// RGBColor is a color specified by red, green, and blue values.
+type RGBColor struct {
+ R uint8
+ G uint8
+ B uint8
+}
+
+// RGBA returns the RGBA value of this color. This satisfies the Go Color
+// interface.
+func (c RGBColor) RGBA() (r, g, b, a uint32) {
+ const shift = 8
+ r |= uint32(c.R) << shift
+ g |= uint32(c.G) << shift
+ b |= uint32(c.B) << shift
+ a = 0xFFFF
+ return
+}
+
+// ANSIColor is a color specified by an ANSI256 color value.
+//
+// Example usage:
+//
+// colorA := lipgloss.ANSIColor(8)
+// colorB := lipgloss.ANSIColor(134)
+type ANSIColor = ansi.IndexedColor
+
+// LightDarkFunc is a function that returns a color based on whether the
+// terminal has a light or dark background. You can create one of these with
+// [LightDark].
+//
+// Example:
+//
+// lightDark := lipgloss.LightDark(hasDarkBackground)
+// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff")
+// myHotColor := lightDark(red, blue)
+//
+// For more info see [LightDark].
+type LightDarkFunc func(light, dark color.Color) color.Color
+
+// LightDark is a simple helper type that can be used to choose the appropriate
+// color based on whether the terminal has a light or dark background.
+//
+// lightDark := lipgloss.LightDark(hasDarkBackground)
+// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff")
+// myHotColor := lightDark(red, blue)
+//
+// In practice, there are slightly different workflows between Bubble Tea and
+// Lip Gloss standalone.
+//
+// In Bubble Tea, listen for tea.BackgroundColorMsg, which automatically
+// flows through Update on start. This message will be received whenever the
+// background color changes:
+//
+// case tea.BackgroundColorMsg:
+// m.hasDarkBackground = msg.IsDark()
+//
+// Later, when you're rendering use:
+//
+// lightDark := lipgloss.LightDark(m.hasDarkBackground)
+// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff")
+// myHotColor := lightDark(red, blue)
+//
+// In standalone Lip Gloss, the workflow is simpler:
+//
+// hasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
+// lightDark := lipgloss.LightDark(hasDarkBG)
+// red, blue := lipgloss.Color("#ff0000"), lipgloss.Color("#0000ff")
+// myHotColor := lightDark(red, blue)
+func LightDark(isDark bool) LightDarkFunc {
+ return func(light, dark color.Color) color.Color {
+ if isDark {
+ return dark
+ }
+ return light
+ }
+}
+
+// isDarkColor returns whether the given color is dark (based on the luminance
+// portion of the color as interpreted as HSL).
+//
+// Example usage:
+//
+// color := lipgloss.Color("#0000ff")
+// if lipgloss.isDarkColor(color) {
+// fmt.Println("It's dark! I love darkness!")
+// } else {
+// fmt.Println("It's light! Cover your eyes!")
+// }
+func isDarkColor(c color.Color) bool {
+ col, ok := colorful.MakeColor(c)
+ if !ok {
+ return true
+ }
+
+ _, _, l := col.Hsl()
+ return l < 0.5 //nolint:mnd
+}
+
+// CompleteFunc is a function that returns the appropriate color based on the
+// given color profile.
+//
+// Example usage:
+//
+// p := colorprofile.Detect(os.Stderr, os.Environ())
+// complete := lipgloss.Complete(p)
+// color := complete(
+// lipgloss.Color(1), // ANSI
+// lipgloss.Color(124), // ANSI256
+// lipgloss.Color("#ff34ac"), // TrueColor
+// )
+// fmt.Println("Ooh, pretty color: ", color)
+//
+// For more info see [Complete].
+type CompleteFunc func(ansi, ansi256, truecolor color.Color) color.Color
+
+// Complete returns a function that will return the appropriate color based on
+// the given color profile.
+//
+// Example usage:
+//
+// p := colorprofile.Detect(os.Stderr, os.Environ())
+// complete := lipgloss.Complete(p)
+// color := complete(
+// lipgloss.Color(1), // ANSI
+// lipgloss.Color(124), // ANSI256
+// lipgloss.Color("#ff34ac"), // TrueColor
+// )
+// fmt.Println("Ooh, pretty color: ", color)
+func Complete(p colorprofile.Profile) CompleteFunc {
+ return func(ansi, ansi256, truecolor color.Color) color.Color {
+ switch p { //nolint:exhaustive
+ case colorprofile.ANSI:
+ return ansi
+ case colorprofile.ANSI256:
+ return ansi256
+ case colorprofile.TrueColor:
+ return truecolor
+ }
+ return noColor
+ }
+}
+
+// ensureNotTransparent ensures that the alpha value of a color is not 0, and if
+// it is, we will set it to 1. This is useful for when we are converting from
+// RGB -> RGBA, and the alpha value is lost in the conversion for gradient purposes.
+func ensureNotTransparent(c color.Color) color.Color {
+ _, _, _, a := c.RGBA()
+ if a == 0 {
+ return Alpha(c, 1)
+ }
+ return c
+}
+
+// Alpha adjusts the alpha value of a color using a 0-1 (clamped) float scale
+// 0 = transparent, 1 = opaque.
+func Alpha(c color.Color, alpha float64) color.Color {
+ if c == nil {
+ return nil
+ }
+
+ r, g, b, _ := c.RGBA()
+ return color.RGBA{
+ R: uint8(min(255, float64(r>>8))),
+ G: uint8(min(255, float64(g>>8))),
+ B: uint8(min(255, float64(b>>8))),
+ A: uint8(clamp(alpha, 0, 1) * 255),
+ }
+}
+
+// Complementary returns the complementary color (180° away on color wheel) of
+// the given color. This is useful for creating a contrasting color.
+func Complementary(c color.Color) color.Color {
+ if c == nil {
+ return nil
+ }
+
+ // Offset hue by 180°.
+ cf, _ := colorful.MakeColor(ensureNotTransparent(c))
+
+ h, s, v := cf.Hsv()
+ h += 180
+ if h >= 360 {
+ h -= 360
+ } else if h < 0 {
+ h += 360
+ }
+
+ return colorful.Hsv(h, s, v).Clamped()
+}
+
+// Darken takes a color and makes it darker by a specific percentage (0-1, clamped).
+func Darken(c color.Color, percent float64) color.Color {
+ if c == nil {
+ return nil
+ }
+
+ mult := 1.0 - clamp(percent, 0, 1)
+
+ r, g, b, a := c.RGBA()
+ return color.RGBA{
+ R: uint8(float64(r>>8) * mult),
+ G: uint8(float64(g>>8) * mult),
+ B: uint8(float64(b>>8) * mult),
+ A: uint8(min(255, float64(a>>8))),
+ }
+}
+
+// Lighten makes a color lighter by a specific percentage (0-1, clamped).
+func Lighten(c color.Color, percent float64) color.Color {
+ if c == nil {
+ return nil
+ }
+
+ add := 255 * (clamp(percent, 0, 1))
+
+ r, g, b, a := c.RGBA()
+ return color.RGBA{
+ R: uint8(min(255, float64(r>>8)+add)),
+ G: uint8(min(255, float64(g>>8)+add)),
+ B: uint8(min(255, float64(b>>8)+add)),
+ A: uint8(min(255, float64(a>>8))),
+ }
+}
diff --git a/vendor/github.com/charmbracelet/lipgloss/get.go b/vendor/charm.land/lipgloss/v2/get.go
similarity index 80%
rename from vendor/github.com/charmbracelet/lipgloss/get.go
rename to vendor/charm.land/lipgloss/v2/get.go
index 422b4ce9..d1fe1d66 100644
--- a/vendor/github.com/charmbracelet/lipgloss/get.go
+++ b/vendor/charm.land/lipgloss/v2/get.go
@@ -1,6 +1,7 @@
package lipgloss
import (
+ "image/color"
"strings"
"github.com/charmbracelet/x/ansi"
@@ -20,7 +21,19 @@ func (s Style) GetItalic() bool {
// GetUnderline returns the style's underline value. If no value is set false is
// returned.
func (s Style) GetUnderline() bool {
- return s.getAsBool(underlineKey, false)
+ return s.ul != UnderlineNone
+}
+
+// GetUnderlineStyle returns the style's underline style. If no value is set
+// UnderlineNone is returned.
+func (s Style) GetUnderlineStyle() Underline {
+ return s.ul
+}
+
+// GetUnderlineColor returns the style's underline color. If no value is set
+// NoColor{} is returned.
+func (s Style) GetUnderlineColor() color.Color {
+ return s.getAsColor(underlineColorKey)
}
// GetStrikethrough returns the style's strikethrough value. If no value is set false
@@ -49,13 +62,13 @@ func (s Style) GetFaint() bool {
// GetForeground returns the style's foreground color. If no value is set
// NoColor{} is returned.
-func (s Style) GetForeground() TerminalColor {
+func (s Style) GetForeground() color.Color {
return s.getAsColor(foregroundKey)
}
// GetBackground returns the style's background color. If no value is set
// NoColor{} is returned.
-func (s Style) GetBackground() TerminalColor {
+func (s Style) GetBackground() color.Color {
return s.getAsColor(backgroundKey)
}
@@ -134,6 +147,16 @@ func (s Style) GetPaddingLeft() int {
return s.getAsInt(paddingLeftKey)
}
+// GetPaddingChar returns the style's padding character. If no value is set a
+// space is returned.
+func (s Style) GetPaddingChar() rune {
+ char := s.getAsRune(paddingCharKey)
+ if char == 0 {
+ return ' '
+ }
+ return char
+}
+
// GetHorizontalPadding returns the style's left and right padding. Unset
// values are measured as 0.
func (s Style) GetHorizontalPadding() int {
@@ -185,6 +208,16 @@ func (s Style) GetMarginLeft() int {
return s.getAsInt(marginLeftKey)
}
+// GetMarginChar returns the style's padding character. If no value is set a
+// space is returned.
+func (s Style) GetMarginChar() rune {
+ char := s.getAsRune(marginCharKey)
+ if char == 0 {
+ return ' '
+ }
+ return char
+}
+
// GetHorizontalMargins returns the style's left and right margins. Unset
// values are measured as 0.
func (s Style) GetHorizontalMargins() int {
@@ -241,49 +274,61 @@ func (s Style) GetBorderLeft() bool {
// GetBorderTopForeground returns the style's border top foreground color. If
// no value is set NoColor{} is returned.
-func (s Style) GetBorderTopForeground() TerminalColor {
+func (s Style) GetBorderTopForeground() color.Color {
return s.getAsColor(borderTopForegroundKey)
}
// GetBorderRightForeground returns the style's border right foreground color.
// If no value is set NoColor{} is returned.
-func (s Style) GetBorderRightForeground() TerminalColor {
+func (s Style) GetBorderRightForeground() color.Color {
return s.getAsColor(borderRightForegroundKey)
}
// GetBorderBottomForeground returns the style's border bottom foreground
// color. If no value is set NoColor{} is returned.
-func (s Style) GetBorderBottomForeground() TerminalColor {
+func (s Style) GetBorderBottomForeground() color.Color {
return s.getAsColor(borderBottomForegroundKey)
}
// GetBorderLeftForeground returns the style's border left foreground
// color. If no value is set NoColor{} is returned.
-func (s Style) GetBorderLeftForeground() TerminalColor {
+func (s Style) GetBorderLeftForeground() color.Color {
return s.getAsColor(borderLeftForegroundKey)
}
+// GetBorderForegroundBlend returns the style's border blend foreground
+// colors. If no value is set, nil is returned.
+func (s Style) GetBorderForegroundBlend() []color.Color {
+ return s.getAsColors(borderForegroundBlendKey)
+}
+
+// GetBorderForegroundBlendOffset returns the style's border blend offset. If no
+// value is set, 0 is returned.
+func (s Style) GetBorderForegroundBlendOffset() int {
+ return s.getAsInt(borderForegroundBlendOffsetKey)
+}
+
// GetBorderTopBackground returns the style's border top background color. If
// no value is set NoColor{} is returned.
-func (s Style) GetBorderTopBackground() TerminalColor {
+func (s Style) GetBorderTopBackground() color.Color {
return s.getAsColor(borderTopBackgroundKey)
}
// GetBorderRightBackground returns the style's border right background color.
// If no value is set NoColor{} is returned.
-func (s Style) GetBorderRightBackground() TerminalColor {
+func (s Style) GetBorderRightBackground() color.Color {
return s.getAsColor(borderRightBackgroundKey)
}
// GetBorderBottomBackground returns the style's border bottom background
// color. If no value is set NoColor{} is returned.
-func (s Style) GetBorderBottomBackground() TerminalColor {
+func (s Style) GetBorderBottomBackground() color.Color {
return s.getAsColor(borderBottomBackgroundKey)
}
// GetBorderLeftBackground returns the style's border left background
// color. If no value is set NoColor{} is returned.
-func (s Style) GetBorderLeftBackground() TerminalColor {
+func (s Style) GetBorderLeftBackground() color.Color {
return s.getAsColor(borderLeftBackgroundKey)
}
@@ -300,7 +345,10 @@ func (s Style) GetBorderTopWidth() int {
// runes of varying widths, the widest rune is returned. If no border exists on
// the top edge, 0 is returned.
func (s Style) GetBorderTopSize() int {
- if !s.getAsBool(borderTopKey, false) && !s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
+ return 1
+ }
+ if !s.getAsBool(borderTopKey, false) {
return 0
}
return s.getBorderStyle().GetTopSize()
@@ -310,7 +358,10 @@ func (s Style) GetBorderTopSize() int {
// runes of varying widths, the widest rune is returned. If no border exists on
// the left edge, 0 is returned.
func (s Style) GetBorderLeftSize() int {
- if !s.getAsBool(borderLeftKey, false) && !s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
+ return 1
+ }
+ if !s.getAsBool(borderLeftKey, false) {
return 0
}
return s.getBorderStyle().GetLeftSize()
@@ -320,7 +371,10 @@ func (s Style) GetBorderLeftSize() int {
// contain runes of varying widths, the widest rune is returned. If no border
// exists on the left edge, 0 is returned.
func (s Style) GetBorderBottomSize() int {
- if !s.getAsBool(borderBottomKey, false) && !s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
+ return 1
+ }
+ if !s.getAsBool(borderBottomKey, false) {
return 0
}
return s.getBorderStyle().GetBottomSize()
@@ -330,7 +384,10 @@ func (s Style) GetBorderBottomSize() int {
// contain runes of varying widths, the widest rune is returned. If no border
// exists on the right edge, 0 is returned.
func (s Style) GetBorderRightSize() int {
- if !s.getAsBool(borderRightKey, false) && !s.implicitBorders() {
+ if s.isBorderStyleSetWithoutSides() {
+ return 1
+ }
+ if !s.getAsBool(borderRightKey, false) {
return 0
}
return s.getBorderStyle().GetRightSize()
@@ -414,11 +471,36 @@ func (s Style) GetTransform() func(string) string {
return s.getAsTransform(transformKey)
}
+// GetHyperlink returns the hyperlink along with its parameters. If no
+// hyperlink is set, empty strings are returned.
+func (s Style) GetHyperlink() (link, params string) {
+ if s.isSet(linkKey) {
+ link = s.link
+ }
+ if s.isSet(linkParamsKey) {
+ params = s.linkParams
+ }
+ return
+}
+
// Returns whether or not the given property is set.
func (s Style) isSet(k propKey) bool {
return s.props.has(k)
}
+func (s Style) getAsRune(k propKey) rune {
+ if !s.isSet(k) {
+ return 0
+ }
+ switch k { //nolint:exhaustive
+ case paddingCharKey:
+ return s.paddingChar
+ case marginCharKey:
+ return s.marginChar
+ }
+ return 0
+}
+
func (s Style) getAsBool(k propKey, defaultVal bool) bool {
if !s.isSet(k) {
return defaultVal
@@ -426,12 +508,25 @@ func (s Style) getAsBool(k propKey, defaultVal bool) bool {
return s.attrs&int(k) != 0
}
-func (s Style) getAsColor(k propKey) TerminalColor {
+func (s Style) getAsColors(k propKey) (colors []color.Color) {
+ if !s.isSet(k) {
+ return nil
+ }
+
+ switch k { //nolint:exhaustive
+ case borderForegroundBlendKey:
+ return s.borderBlendFgColor
+ }
+
+ return nil
+}
+
+func (s Style) getAsColor(k propKey) color.Color {
if !s.isSet(k) {
return noColor
}
- var c TerminalColor
+ var c color.Color
switch k { //nolint:exhaustive
case foregroundKey:
c = s.fgColor
@@ -455,6 +550,8 @@ func (s Style) getAsColor(k propKey) TerminalColor {
c = s.borderBottomBgColor
case borderLeftBackgroundKey:
c = s.borderLeftBgColor
+ case underlineColorKey:
+ c = s.ulColor
}
if c != nil {
@@ -489,6 +586,8 @@ func (s Style) getAsInt(k propKey) int {
return s.marginBottom
case marginLeftKey:
return s.marginLeft
+ case borderForegroundBlendOffsetKey:
+ return s.borderForegroundBlendOffset
case maxWidthKey:
return s.maxWidth
case maxHeightKey:
@@ -519,20 +618,6 @@ func (s Style) getBorderStyle() Border {
return s.borderStyle
}
-// Returns whether or not the style has implicit borders. This happens when
-// a border style has been set but no border sides have been explicitly turned
-// on or off.
-func (s Style) implicitBorders() bool {
- var (
- borderStyle = s.getBorderStyle()
- topSet = s.isSet(borderTopKey)
- rightSet = s.isSet(borderRightKey)
- bottomSet = s.isSet(borderBottomKey)
- leftSet = s.isSet(borderLeftKey)
- )
- return borderStyle != noBorder && !(topSet || rightSet || bottomSet || leftSet)
-}
-
func (s Style) getAsTransform(propKey) func(string) string {
if !s.isSet(transformKey) {
return nil
@@ -543,6 +628,8 @@ func (s Style) getAsTransform(propKey) func(string) string {
// Split a string into lines, additionally returning the size of the widest
// line.
func getLines(s string) (lines []string, widest int) {
+ s = strings.ReplaceAll(s, "\t", " ")
+ s = strings.ReplaceAll(s, "\r\n", "\n")
lines = strings.Split(s, "\n")
for _, l := range lines {
@@ -554,3 +641,17 @@ func getLines(s string) (lines []string, widest int) {
return lines, widest
}
+
+// isBorderStyleSetWithoutSides returns true if the border style is set but no
+// sides are set. This is used to determine if the border should be rendered by
+// default.
+func (s Style) isBorderStyleSetWithoutSides() bool {
+ var (
+ border = s.getBorderStyle()
+ topSet = s.isSet(borderTopKey)
+ rightSet = s.isSet(borderRightKey)
+ bottomSet = s.isSet(borderBottomKey)
+ leftSet = s.isSet(borderLeftKey)
+ )
+ return border != noBorder && !(topSet || rightSet || bottomSet || leftSet) //nolint:staticcheck
+}
diff --git a/vendor/github.com/charmbracelet/lipgloss/join.go b/vendor/charm.land/lipgloss/v2/join.go
similarity index 97%
rename from vendor/github.com/charmbracelet/lipgloss/join.go
rename to vendor/charm.land/lipgloss/v2/join.go
index b0a23a54..349ae552 100644
--- a/vendor/github.com/charmbracelet/lipgloss/join.go
+++ b/vendor/charm.land/lipgloss/v2/join.go
@@ -60,7 +60,7 @@ func JoinHorizontal(pos Position, strs ...string) string {
extraLines := make([]string, maxHeight-len(blocks[i]))
- switch pos { //nolint:exhaustive
+ switch pos {
case Top:
blocks[i] = append(blocks[i], extraLines...)
@@ -139,7 +139,7 @@ func JoinVertical(pos Position, strs ...string) string {
for j, line := range block {
w := maxWidth - ansi.StringWidth(line)
- switch pos { //nolint:exhaustive
+ switch pos {
case Left:
b.WriteString(line)
b.WriteString(strings.Repeat(" ", w))
@@ -165,7 +165,7 @@ func JoinVertical(pos Position, strs ...string) string {
// Write a newline as long as we're not on the last line of the
// last block.
- if !(i == len(blocks)-1 && j == len(block)-1) {
+ if !(i == len(blocks)-1 && j == len(block)-1) { //nolint:staticcheck
b.WriteRune('\n')
}
}
diff --git a/vendor/charm.land/lipgloss/v2/layer.go b/vendor/charm.land/lipgloss/v2/layer.go
new file mode 100644
index 00000000..e30d1ef2
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/layer.go
@@ -0,0 +1,327 @@
+package lipgloss
+
+import (
+ "fmt"
+ "image"
+ "slices"
+
+ uv "github.com/charmbracelet/ultraviolet"
+)
+
+// Layer represents a visual layer with content and positioning. It's a pure
+// data structure that defines the layer hierarchy without any computation.
+type Layer struct {
+ id string
+ content string
+ width, height int
+ x, y, z int
+ layers []*Layer
+}
+
+// NewLayer creates a new [Layer] with the given content and optional child layers.
+func NewLayer(content string, layers ...*Layer) *Layer {
+ l := &Layer{
+ content: content,
+ }
+ l.AddLayers(layers...)
+ return l
+}
+
+// GetContent returns the content of the Layer.
+func (l *Layer) GetContent() string {
+ return l.content
+}
+
+// Width returns the width of the Layer.
+func (l *Layer) Width() int {
+ return l.width
+}
+
+// Height returns the height of the Layer.
+func (l *Layer) Height() int {
+ return l.height
+}
+
+// GetID returns the ID of the Layer.
+func (l *Layer) GetID() string {
+ return l.id
+}
+
+// ID sets the ID of the Layer.
+func (l *Layer) ID(id string) *Layer {
+ l.id = id
+ return l
+}
+
+// X sets the x-coordinate of the Layer relative to its parent.
+func (l *Layer) X(x int) *Layer {
+ l.x = x
+ return l
+}
+
+// Y sets the y-coordinate of the Layer relative to its parent.
+func (l *Layer) Y(y int) *Layer {
+ l.y = y
+ return l
+}
+
+// Z sets the z-index of the Layer relative to its parent.
+func (l *Layer) Z(z int) *Layer {
+ l.z = z
+ return l
+}
+
+// GetX returns the x-coordinate of the Layer relative to its parent.
+func (l *Layer) GetX() int {
+ return l.x
+}
+
+// GetY returns the y-coordinate of the Layer relative to its parent.
+func (l *Layer) GetY() int {
+ return l.y
+}
+
+// GetZ returns the z-index of the Layer relative to its parent.
+func (l *Layer) GetZ() int {
+ return l.z
+}
+
+// AddLayers adds child layers to the Layer.
+func (l *Layer) AddLayers(layers ...*Layer) *Layer {
+ for i, layer := range layers {
+ if layer == nil {
+ panic(fmt.Sprintf("layer at index %d is nil", i))
+ }
+ l.layers = append(l.layers, layer)
+ }
+ area := l.boundsWithOffset(0, 0)
+ l.width = area.Dx()
+ l.height = area.Dy()
+ return l
+}
+
+// GetLayer returns a descendant layer by its ID, or nil if not found.
+// Layers with empty IDs are skipped.
+func (l *Layer) GetLayer(id string) *Layer {
+ if id == "" {
+ return nil
+ }
+ if l.id == id {
+ return l
+ }
+ for _, child := range l.layers {
+ if found := child.GetLayer(id); found != nil {
+ return found
+ }
+ }
+ return nil
+}
+
+// MaxZ returns the maximum z-index among this layer and all its descendants.
+func (l *Layer) MaxZ() int {
+ maxZ := l.z
+ for _, child := range l.layers {
+ childMaxZ := child.MaxZ()
+ if childMaxZ > maxZ {
+ maxZ = childMaxZ
+ }
+ }
+ return maxZ
+}
+
+// boundsWithOffset calculates bounds with parent offset applied.
+func (l *Layer) boundsWithOffset(parentX, parentY int) image.Rectangle {
+ absX := l.x + parentX
+ absY := l.y + parentY
+
+ width, height := Width(l.content), Height(l.content)
+ bounds := image.Rectangle{
+ Min: image.Pt(absX, absY),
+ Max: image.Pt(absX+width, absY+height),
+ }
+
+ for _, child := range l.layers {
+ bounds = bounds.Union(child.boundsWithOffset(absX, absY))
+ }
+
+ return bounds
+}
+
+var _ uv.Drawable = (*Layer)(nil)
+
+// Draw draws the content of the layer on the screen at the specified area.
+func (l *Layer) Draw(scr uv.Screen, area uv.Rectangle) {
+ content := uv.NewStyledString(l.content)
+ content.Draw(scr, area)
+}
+
+// LayerHit represents the result of a hit test on a [Layer].
+type LayerHit struct {
+ id string
+ layer *Layer
+ bounds image.Rectangle
+}
+
+// Empty returns true if the LayerHit represents no hit.
+func (lh LayerHit) Empty() bool {
+ return lh.layer == nil
+}
+
+// ID returns the ID of the hit Layer.
+func (lh LayerHit) ID() string {
+ return lh.id
+}
+
+// Layer returns the layer that was hit.
+func (lh LayerHit) Layer() *Layer {
+ return lh.layer
+}
+
+// Bounds returns the bounds of the LayerHit.
+func (lh LayerHit) Bounds() image.Rectangle {
+ return lh.bounds
+}
+
+// Compositor manages the composition of layers. It flattens a layer hierarchy
+// once and provides efficient drawing and hit testing operations. All computation
+// related to layers happens in the Compositor.
+type Compositor struct {
+ root *Layer
+ layers []compositeLayer
+ index map[string]*Layer
+ bounds image.Rectangle
+}
+
+// compositeLayer holds a flattened layer with its calculated absolute position and bounds.
+type compositeLayer struct {
+ layer *Layer
+ absX int
+ absY int
+ bounds image.Rectangle
+}
+
+// NewCompositor creates a new Compositor with an internal root layer. Optional
+// layers can be provided which will be added as children of the root. The layer
+// hierarchy is flattened and sorted by z-index for efficient rendering and hit testing.
+func NewCompositor(layers ...*Layer) *Compositor {
+ root := NewLayer("")
+ root.AddLayers(layers...)
+ c := &Compositor{
+ root: root,
+ index: make(map[string]*Layer),
+ }
+ c.flatten()
+ return c
+}
+
+// AddLayers adds layers to the compositor's root and refreshes the internal state.
+func (c *Compositor) AddLayers(layers ...*Layer) *Compositor {
+ c.root.AddLayers(layers...)
+ c.flatten()
+ return c
+}
+
+// flatten builds the internal flattened layer list and calculates overall bounds.
+func (c *Compositor) flatten() {
+ c.layers = nil
+ c.index = make(map[string]*Layer)
+ c.flattenRecursive(c.root, 0, 0)
+
+ // Sort by absolute z-index (lowest to highest for drawing)
+ slices.SortFunc(c.layers, func(a, b compositeLayer) int {
+ return a.layer.z - b.layer.z
+ })
+
+ // Calculate overall bounds
+ if len(c.layers) > 0 {
+ c.bounds = c.layers[0].bounds
+ for i := 1; i < len(c.layers); i++ {
+ c.bounds = c.bounds.Union(c.layers[i].bounds)
+ }
+ }
+}
+
+// flattenRecursive recursively collects all layers with their absolute positions.
+func (c *Compositor) flattenRecursive(layer *Layer, parentX, parentY int) {
+ absX := layer.x + parentX
+ absY := layer.y + parentY
+
+ width, height := Width(layer.content), Height(layer.content)
+ bounds := image.Rectangle{
+ Min: image.Pt(absX, absY),
+ Max: image.Pt(absX+width, absY+height),
+ }
+
+ c.layers = append(c.layers, compositeLayer{
+ layer: layer,
+ absX: absX,
+ absY: absY,
+ bounds: bounds,
+ })
+
+ // Index layer by ID if it has one
+ if layer.id != "" {
+ c.index[layer.id] = layer
+ }
+
+ for _, child := range layer.layers {
+ c.flattenRecursive(child, absX, absY)
+ }
+}
+
+// Bounds returns the overall bounds of all layers in the compositor.
+func (c *Compositor) Bounds() image.Rectangle {
+ return c.bounds
+}
+
+// Draw draws all layers onto the given [uv.Screen] in z-index order.
+func (c *Compositor) Draw(scr uv.Screen, area image.Rectangle) {
+ for _, cl := range c.layers {
+ if cl.bounds.Overlaps(area) {
+ cl.layer.Draw(scr, cl.bounds)
+ }
+ }
+}
+
+// Hit performs a hit test at the given (x, y) coordinates. If a layer is hit,
+// it returns the ID of the top-most layer at that point. Layers with empty IDs
+// are ignored. If no layer is hit, it returns an empty [LayerHit].
+func (c *Compositor) Hit(x, y int) LayerHit {
+ var hit LayerHit
+ pt := image.Pt(x, y)
+ // Check from highest z to lowest (reverse order)
+ for i := len(c.layers) - 1; i >= 0; i-- {
+ cl := c.layers[i]
+ if cl.layer.id != "" && pt.In(cl.bounds) {
+ hit.id = cl.layer.id
+ hit.layer = cl.layer
+ hit.bounds = cl.bounds
+ return hit
+ }
+ }
+ return hit
+}
+
+// GetLayer returns a layer by its ID, or nil if not found.
+// Layers with empty IDs are not indexed and cannot be retrieved.
+func (c *Compositor) GetLayer(id string) *Layer {
+ if id == "" {
+ return nil
+ }
+ return c.index[id]
+}
+
+// Refresh re-flattens the layer hierarchy. Call this after modifying the layer
+// tree structure or positions to update the compositor's internal state.
+func (c *Compositor) Refresh() {
+ c.flatten()
+}
+
+// Render renders the compositor into a styled string. This is a helper
+// function that creates a temporary canvas, draws the compositor onto it, and
+// returns the resulting string.
+func (c *Compositor) Render() string {
+ width, height := c.bounds.Dx(), c.bounds.Dy()
+ canvas := NewCanvas(width, height)
+ return canvas.Compose(c).Render()
+}
diff --git a/vendor/charm.land/lipgloss/v2/lipgloss.go b/vendor/charm.land/lipgloss/v2/lipgloss.go
new file mode 100644
index 00000000..3fb4e6f2
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/lipgloss.go
@@ -0,0 +1,3 @@
+// Package lipgloss provides style definitions for nice terminal layouts. Built
+// with TUIs in mind.
+package lipgloss
diff --git a/vendor/github.com/charmbracelet/lipgloss/position.go b/vendor/charm.land/lipgloss/v2/position.go
similarity index 69%
rename from vendor/github.com/charmbracelet/lipgloss/position.go
rename to vendor/charm.land/lipgloss/v2/position.go
index 185f5af3..ce91442d 100644
--- a/vendor/github.com/charmbracelet/lipgloss/position.go
+++ b/vendor/charm.land/lipgloss/v2/position.go
@@ -34,26 +34,13 @@ const (
// Place places a string or text block vertically in an unstyled box of a given
// width or height.
func Place(width, height int, hPos, vPos Position, str string, opts ...WhitespaceOption) string {
- return renderer.Place(width, height, hPos, vPos, str, opts...)
-}
-
-// Place places a string or text block vertically in an unstyled box of a given
-// width or height.
-func (r *Renderer) Place(width, height int, hPos, vPos Position, str string, opts ...WhitespaceOption) string {
- return r.PlaceVertical(height, vPos, r.PlaceHorizontal(width, hPos, str, opts...), opts...)
-}
-
-// PlaceHorizontal places a string or text block horizontally in an unstyled
-// block of a given width. If the given width is shorter than the max width of
-// the string (measured by its longest line) this will be a noop.
-func PlaceHorizontal(width int, pos Position, str string, opts ...WhitespaceOption) string {
- return renderer.PlaceHorizontal(width, pos, str, opts...)
+ return PlaceVertical(height, vPos, PlaceHorizontal(width, hPos, str, opts...), opts...)
}
// PlaceHorizontal places a string or text block horizontally in an unstyled
// block of a given width. If the given width is shorter than the max width of
// the string (measured by its longest line) this will be a noöp.
-func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ...WhitespaceOption) string {
+func PlaceHorizontal(width int, pos Position, str string, opts ...WhitespaceOption) string {
lines, contentWidth := getLines(str)
gap := width - contentWidth
@@ -61,14 +48,14 @@ func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ...
return str
}
- ws := newWhitespace(r, opts...)
+ ws := newWhitespace(opts...)
var b strings.Builder
for i, l := range lines {
// Is this line shorter than the longest line?
short := max(0, contentWidth-ansi.StringWidth(l))
- switch pos { //nolint:exhaustive
+ switch pos {
case Left:
b.WriteString(l)
b.WriteString(ws.render(gap + short))
@@ -97,17 +84,10 @@ func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ...
return b.String()
}
-// PlaceVertical places a string or text block vertically in an unstyled block
-// of a given height. If the given height is shorter than the height of the
-// string (measured by its newlines) then this will be a noop.
-func PlaceVertical(height int, pos Position, str string, opts ...WhitespaceOption) string {
- return renderer.PlaceVertical(height, pos, str, opts...)
-}
-
// PlaceVertical places a string or text block vertically in an unstyled block
// of a given height. If the given height is shorter than the height of the
// string (measured by its newlines) then this will be a noöp.
-func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...WhitespaceOption) string {
+func PlaceVertical(height int, pos Position, str string, opts ...WhitespaceOption) string {
contentHeight := strings.Count(str, "\n") + 1
gap := height - contentHeight
@@ -115,17 +95,17 @@ func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...W
return str
}
- ws := newWhitespace(r, opts...)
+ ws := newWhitespace(opts...)
_, width := getLines(str)
emptyLine := ws.render(width)
b := strings.Builder{}
- switch pos { //nolint:exhaustive
+ switch pos {
case Top:
b.WriteString(str)
b.WriteRune('\n')
- for i := 0; i < gap; i++ {
+ for i := range gap {
b.WriteString(emptyLine)
if i < gap-1 {
b.WriteRune('\n')
@@ -144,7 +124,7 @@ func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...W
b.WriteString(strings.Repeat(emptyLine+"\n", top))
b.WriteString(str)
- for i := 0; i < bottom; i++ {
+ for range bottom {
b.WriteRune('\n')
b.WriteString(emptyLine)
}
diff --git a/vendor/charm.land/lipgloss/v2/query.go b/vendor/charm.land/lipgloss/v2/query.go
new file mode 100644
index 00000000..96cd5b94
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/query.go
@@ -0,0 +1,92 @@
+package lipgloss
+
+import (
+ "fmt"
+ "image/color"
+ "os"
+ "runtime"
+
+ "github.com/charmbracelet/x/term"
+)
+
+func backgroundColor(in term.File, out term.File) (color.Color, error) {
+ state, err := term.MakeRaw(in.Fd())
+ if err != nil {
+ return nil, fmt.Errorf("error setting raw state to detect background color: %w", err)
+ }
+
+ defer term.Restore(in.Fd(), state) //nolint:errcheck
+
+ bg, err := queryBackgroundColor(in, out)
+ if err != nil {
+ return nil, err
+ }
+
+ return bg, nil
+}
+
+// BackgroundColor queries the terminal's background color. Typically, you'll
+// want to query against stdin and either stdout or stderr, depending on what
+// you're writing to.
+//
+// This function is intended for standalone Lip Gloss use only. If you're using
+// Bubble Tea, listen for tea.BackgroundColorMsg in your update function.
+func BackgroundColor(in term.File, out term.File) (bg color.Color, err error) {
+ if runtime.GOOS == "windows" { //nolint:nestif
+ // On Windows, when the input/output is redirected or piped, we need to
+ // open the console explicitly.
+ // See https://learn.microsoft.com/en-us/windows/console/getstdhandle#remarks
+ if !term.IsTerminal(in.Fd()) {
+ f, err := os.OpenFile("CONIN$", os.O_RDWR, 0o644) //nolint:gosec
+ if err != nil {
+ return nil, fmt.Errorf("error opening CONIN$: %w", err)
+ }
+ in = f
+ }
+ if !term.IsTerminal(out.Fd()) {
+ f, err := os.OpenFile("CONOUT$", os.O_RDWR, 0o644) //nolint:gosec
+ if err != nil {
+ return nil, fmt.Errorf("error opening CONOUT$: %w", err)
+ }
+ out = f
+ }
+ return backgroundColor(in, out)
+ }
+
+ // NOTE: On Unix, one of the given files must be a tty.
+ if !term.IsTerminal(in.Fd()) || !term.IsTerminal(out.Fd()) {
+ return nil, fmt.Errorf("input/output is not a terminal")
+ }
+ for _, f := range []term.File{in, out} {
+ if bg, err = backgroundColor(f, f); err == nil {
+ return bg, nil
+ }
+ }
+
+ return bg, err
+}
+
+// HasDarkBackground detects whether the terminal has a light or dark
+// background.
+//
+// Typically, you'll want to query against stdin and either stdout or stderr
+// depending on what you're writing to.
+//
+// hasDarkBG := HasDarkBackground(os.Stdin, os.Stdout)
+// lightDark := LightDark(hasDarkBG)
+// myHotColor := lightDark("#ff0000", "#0000ff")
+//
+// This is intended for use in standalone Lip Gloss only. In Bubble Tea, listen
+// for tea.BackgroundColorMsg in your Update function.
+//
+// case tea.BackgroundColorMsg:
+// hasDarkBackground = msg.IsDark()
+//
+// By default, this function will return true if it encounters an error.
+func HasDarkBackground(in term.File, out term.File) bool {
+ bg, err := BackgroundColor(in, out)
+ if err != nil || bg == nil {
+ return true
+ }
+ return isDarkColor(bg)
+}
diff --git a/vendor/github.com/charmbracelet/lipgloss/ranges.go b/vendor/charm.land/lipgloss/v2/ranges.go
similarity index 75%
rename from vendor/github.com/charmbracelet/lipgloss/ranges.go
rename to vendor/charm.land/lipgloss/v2/ranges.go
index d1716998..bb209f0e 100644
--- a/vendor/github.com/charmbracelet/lipgloss/ranges.go
+++ b/vendor/charm.land/lipgloss/v2/ranges.go
@@ -6,9 +6,8 @@ import (
"github.com/charmbracelet/x/ansi"
)
-// StyleRanges allows to, given a string, style ranges of it differently.
-// The function will take into account existing styles.
-// Ranges should not overlap.
+// StyleRanges applying styling to ranges in a string. Existing styles will be
+// taken into account. Ranges should not overlap.
func StyleRanges(s string, ranges ...Range) string {
if len(ranges) == 0 {
return s
@@ -36,12 +35,13 @@ func StyleRanges(s string, ranges ...Range) string {
return buf.String()
}
-// NewRange returns a range that can be used with [StyleRanges].
+// NewRange returns a range and style that can be used with [StyleRanges].
func NewRange(start, end int, style Style) Range {
return Range{start, end, style}
}
-// Range to be used with [StyleRanges].
+// Range is a range of text and associated styling to be used with
+// [StyleRanges].
type Range struct {
Start, End int
Style Style
diff --git a/vendor/github.com/charmbracelet/lipgloss/runes.go b/vendor/charm.land/lipgloss/v2/runes.go
similarity index 100%
rename from vendor/github.com/charmbracelet/lipgloss/runes.go
rename to vendor/charm.land/lipgloss/v2/runes.go
diff --git a/vendor/github.com/charmbracelet/lipgloss/set.go b/vendor/charm.land/lipgloss/v2/set.go
similarity index 78%
rename from vendor/github.com/charmbracelet/lipgloss/set.go
rename to vendor/charm.land/lipgloss/v2/set.go
index fde38fae..f10b4538 100644
--- a/vendor/github.com/charmbracelet/lipgloss/set.go
+++ b/vendor/charm.land/lipgloss/v2/set.go
@@ -1,16 +1,25 @@
package lipgloss
+import (
+ "image/color"
+ "strings"
+)
+
// Set a value on the underlying rules map.
-func (s *Style) set(key propKey, value interface{}) {
+func (s *Style) set(key propKey, value any) {
// We don't allow negative integers on any of our other values, so just keep
// them at zero or above. We could use uints instead, but the
// conversions are a little tedious, so we're sticking with ints for
// sake of usability.
- switch key { //nolint:exhaustive
+ switch key {
case foregroundKey:
s.fgColor = colorOrNil(value)
case backgroundKey:
s.bgColor = colorOrNil(value)
+ case underlineColorKey:
+ s.ulColor = colorOrNil(value)
+ case underlineKey:
+ s.ul = value.(Underline)
case widthKey:
s.width = max(0, value.(int))
case heightKey:
@@ -27,6 +36,8 @@ func (s *Style) set(key propKey, value interface{}) {
s.paddingBottom = max(0, value.(int))
case paddingLeftKey:
s.paddingLeft = max(0, value.(int))
+ case paddingCharKey:
+ s.paddingChar = value.(rune)
case marginTopKey:
s.marginTop = max(0, value.(int))
case marginRightKey:
@@ -37,6 +48,8 @@ func (s *Style) set(key propKey, value interface{}) {
s.marginLeft = max(0, value.(int))
case marginBackgroundKey:
s.marginBgColor = colorOrNil(value)
+ case marginCharKey:
+ s.marginChar = value.(rune)
case borderStyleKey:
s.borderStyle = value.(Border)
case borderTopForegroundKey:
@@ -47,6 +60,10 @@ func (s *Style) set(key propKey, value interface{}) {
s.borderBottomFgColor = colorOrNil(value)
case borderLeftForegroundKey:
s.borderLeftFgColor = colorOrNil(value)
+ case borderForegroundBlendKey:
+ s.borderBlendFgColor = value.([]color.Color)
+ case borderForegroundBlendOffsetKey:
+ s.borderForegroundBlendOffset = value.(int)
case borderTopBackgroundKey:
s.borderTopBgColor = colorOrNil(value)
case borderRightBackgroundKey:
@@ -65,6 +82,10 @@ func (s *Style) set(key propKey, value interface{}) {
s.tabWidth = value.(int)
case transformKey:
s.transform = value.(func(string) string)
+ case linkKey:
+ s.link = value.(string)
+ case linkParamsKey:
+ s.linkParams = value.(string)
default:
if v, ok := value.(bool); ok { //nolint:nestif
if v {
@@ -88,11 +109,15 @@ func (s *Style) set(key propKey, value interface{}) {
// setFrom sets the property from another style.
func (s *Style) setFrom(key propKey, i Style) {
- switch key { //nolint:exhaustive
+ switch key {
case foregroundKey:
s.set(foregroundKey, i.fgColor)
case backgroundKey:
s.set(backgroundKey, i.bgColor)
+ case underlineColorKey:
+ s.set(underlineColorKey, i.ulColor)
+ case underlineKey:
+ s.set(underlineKey, i.ul)
case widthKey:
s.set(widthKey, i.width)
case heightKey:
@@ -109,6 +134,8 @@ func (s *Style) setFrom(key propKey, i Style) {
s.set(paddingBottomKey, i.paddingBottom)
case paddingLeftKey:
s.set(paddingLeftKey, i.paddingLeft)
+ case paddingCharKey:
+ s.set(paddingCharKey, i.paddingChar)
case marginTopKey:
s.set(marginTopKey, i.marginTop)
case marginRightKey:
@@ -119,6 +146,8 @@ func (s *Style) setFrom(key propKey, i Style) {
s.set(marginLeftKey, i.marginLeft)
case marginBackgroundKey:
s.set(marginBackgroundKey, i.marginBgColor)
+ case marginCharKey:
+ s.set(marginCharKey, i.marginChar)
case borderStyleKey:
s.set(borderStyleKey, i.borderStyle)
case borderTopForegroundKey:
@@ -129,6 +158,10 @@ func (s *Style) setFrom(key propKey, i Style) {
s.set(borderBottomForegroundKey, i.borderBottomFgColor)
case borderLeftForegroundKey:
s.set(borderLeftForegroundKey, i.borderLeftFgColor)
+ case borderForegroundBlendKey:
+ s.set(borderForegroundBlendKey, i.borderBlendFgColor)
+ case borderForegroundBlendOffsetKey:
+ s.set(borderForegroundBlendOffsetKey, i.borderForegroundBlendOffset)
case borderTopBackgroundKey:
s.set(borderTopBackgroundKey, i.borderTopBgColor)
case borderRightBackgroundKey:
@@ -151,8 +184,8 @@ func (s *Style) setFrom(key propKey, i Style) {
}
}
-func colorOrNil(c interface{}) TerminalColor {
- if c, ok := c.(TerminalColor); ok {
+func colorOrNil(c any) color.Color {
+ if c, ok := c.(color.Color); ok {
return c
}
return nil
@@ -173,9 +206,33 @@ func (s Style) Italic(v bool) Style {
// Underline sets an underline rule. By default, underlines will not be drawn on
// whitespace like margins and padding. To change this behavior set
-// UnderlineSpaces.
+// [Style.UnderlineSpaces].
func (s Style) Underline(v bool) Style {
- s.set(underlineKey, v)
+ if v {
+ return s.UnderlineStyle(UnderlineSingle)
+ }
+ return s.UnderlineStyle(UnderlineNone)
+}
+
+// UnderlineStyle sets the underline style. This can be used to set the underline
+// to be a single, double, curly, dotted, or dashed line.
+//
+// Note that not all terminal emulators support underline styles. If a style is
+// not supported, it will typically fall back to a single underline but this is
+// not guaranteed. This depends on the terminal emulator being used.
+func (s Style) UnderlineStyle(u Underline) Style {
+ s.set(underlineKey, u)
+ return s
+}
+
+// UnderlineColor sets the color of the underline. By default, the underline
+// will be the same color as the foreground.
+//
+// Note that not all terminal emulators support colored underlines. If color is
+// not supported, it might produce unexpected results. This depends on the
+// terminal emulator being used.
+func (s Style) UnderlineColor(c color.Color) Style {
+ s.set(underlineColorKey, c)
return s
}
@@ -212,19 +269,20 @@ func (s Style) Faint(v bool) Style {
//
// // Removes the foreground color
// s.Foreground(lipgloss.NoColor)
-func (s Style) Foreground(c TerminalColor) Style {
+func (s Style) Foreground(c color.Color) Style {
s.set(foregroundKey, c)
return s
}
// Background sets a background color.
-func (s Style) Background(c TerminalColor) Style {
+func (s Style) Background(c color.Color) Style {
s.set(backgroundKey, c)
return s
}
-// Width sets the width of the block before applying margins. The width, if
-// set, also determines where text will wrap.
+// Width sets the width of the block before applying margins. This means your
+// styled content will exactly equal the size set here. Text will wrap based on
+// Padding and Borders set on the style.
func (s Style) Width(i int) Style {
s.set(widthKey, i)
return s
@@ -317,6 +375,18 @@ func (s Style) PaddingBottom(i int) Style {
return s
}
+// PaddingChar sets the character used for padding. This is useful for
+// rendering blocks with a specific character, such as a space or a dot.
+// Example of using [NBSP] as padding to prevent line breaks:
+//
+// ```go
+// s := lipgloss.NewStyle().PaddingChar(lipgloss.NBSP)
+// ```
+func (s Style) PaddingChar(r rune) Style {
+ s.set(paddingCharKey, r)
+ return s
+}
+
// ColorWhitespace determines whether or not the background color should be
// applied to the padding. This is true by default as it's more than likely the
// desired and expected behavior, but it can be disabled for certain graphic
@@ -382,11 +452,18 @@ func (s Style) MarginBottom(i int) Style {
// MarginBackground sets the background color of the margin. Note that this is
// also set when inheriting from a style with a background color. In that case
// the background color on that style will set the margin color on this style.
-func (s Style) MarginBackground(c TerminalColor) Style {
+func (s Style) MarginBackground(c color.Color) Style {
s.set(marginBackgroundKey, c)
return s
}
+// MarginChar sets the character used for the margin. This is useful for
+// rendering blocks with a specific character, such as a space or a dot.
+func (s Style) MarginChar(r rune) Style {
+ s.set(marginCharKey, r)
+ return s
+}
+
// Border is shorthand for setting the border style and which sides should
// have a border at once. The variadic argument sides works as follows:
//
@@ -487,7 +564,7 @@ func (s Style) BorderLeft(v bool) Style {
// top side, followed by the right side, then the bottom, and finally the left.
//
// With more than four arguments nothing will be set.
-func (s Style) BorderForeground(c ...TerminalColor) Style {
+func (s Style) BorderForeground(c ...color.Color) Style {
if len(c) == 0 {
return s
}
@@ -506,32 +583,80 @@ func (s Style) BorderForeground(c ...TerminalColor) Style {
}
// BorderTopForeground set the foreground color for the top of the border.
-func (s Style) BorderTopForeground(c TerminalColor) Style {
+func (s Style) BorderTopForeground(c color.Color) Style {
s.set(borderTopForegroundKey, c)
return s
}
// BorderRightForeground sets the foreground color for the right side of the
// border.
-func (s Style) BorderRightForeground(c TerminalColor) Style {
+func (s Style) BorderRightForeground(c color.Color) Style {
s.set(borderRightForegroundKey, c)
return s
}
// BorderBottomForeground sets the foreground color for the bottom of the
// border.
-func (s Style) BorderBottomForeground(c TerminalColor) Style {
+func (s Style) BorderBottomForeground(c color.Color) Style {
s.set(borderBottomForegroundKey, c)
return s
}
// BorderLeftForeground sets the foreground color for the left side of the
// border.
-func (s Style) BorderLeftForeground(c TerminalColor) Style {
+func (s Style) BorderLeftForeground(c color.Color) Style {
s.set(borderLeftForegroundKey, c)
return s
}
+// BorderForegroundBlend sets the foreground colors for the border blend. At least
+// 2 colors are required to use blending, otherwise this will no-op with 0 colors,
+// and pass to BorderForeground with 1 color. This will override all other border
+// foreground colors when used.
+//
+// When providing colors, in most cases (e.g. when all border sides are enabled),
+// you will want to provide a wrapping-set of colors, so the start and end color
+// are either the same, or very similar. For example:
+//
+// lipgloss.NewStyle().BorderForegroundBlend(
+// lipgloss.Color("#00FA68"),
+// lipgloss.Color("#9900FF"),
+// lipgloss.Color("#ED5353"),
+// lipgloss.Color("#9900FF"),
+// lipgloss.Color("#00FA68"),
+// )
+func (s Style) BorderForegroundBlend(c ...color.Color) Style {
+ if len(c) == 0 {
+ return s
+ }
+
+ // Insufficient colors to use blending, pass to BorderForeground.
+ if len(c) == 1 {
+ return s.BorderForeground(c...)
+ }
+
+ s.set(borderForegroundBlendKey, c)
+ return s
+}
+
+// BorderForegroundBlendOffset sets the border blend offset cells, starting from
+// the top left corner. Value can be positive or negative, and does not need to
+// equal the dimensions of the border region. Direction (when positive) is as
+// follows ("o" is starting point):
+//
+// o -------->
+// ┌──────────┐
+// ^ │ │ |
+// | │ │ |
+// | │ │ |
+// | │ │ v
+// └──────────┘
+// <---------
+func (s Style) BorderForegroundBlendOffset(v int) Style {
+ s.set(borderForegroundBlendOffsetKey, v)
+ return s
+}
+
// BorderBackground is a shorthand function for setting all of the
// background colors of the borders at once. The arguments work as follows:
//
@@ -547,7 +672,7 @@ func (s Style) BorderLeftForeground(c TerminalColor) Style {
// top side, followed by the right side, then the bottom, and finally the left.
//
// With more than four arguments nothing will be set.
-func (s Style) BorderBackground(c ...TerminalColor) Style {
+func (s Style) BorderBackground(c ...color.Color) Style {
if len(c) == 0 {
return s
}
@@ -566,27 +691,27 @@ func (s Style) BorderBackground(c ...TerminalColor) Style {
}
// BorderTopBackground sets the background color of the top of the border.
-func (s Style) BorderTopBackground(c TerminalColor) Style {
+func (s Style) BorderTopBackground(c color.Color) Style {
s.set(borderTopBackgroundKey, c)
return s
}
// BorderRightBackground sets the background color of right side the border.
-func (s Style) BorderRightBackground(c TerminalColor) Style {
+func (s Style) BorderRightBackground(c color.Color) Style {
s.set(borderRightBackgroundKey, c)
return s
}
// BorderBottomBackground sets the background color of the bottom of the
// border.
-func (s Style) BorderBottomBackground(c TerminalColor) Style {
+func (s Style) BorderBottomBackground(c color.Color) Style {
s.set(borderBottomBackgroundKey, c)
return s
}
// BorderLeftBackground set the background color of the left side of the
// border.
-func (s Style) BorderLeftBackground(c TerminalColor) Style {
+func (s Style) BorderLeftBackground(c color.Color) Style {
s.set(borderLeftBackgroundKey, c)
return s
}
@@ -685,10 +810,18 @@ func (s Style) Transform(fn func(string) string) Style {
return s
}
-// Renderer sets the renderer for the style. This is useful for changing the
-// renderer for a style that is being used in a different context.
-func (s Style) Renderer(r *Renderer) Style {
- s.r = r
+// Hyperlink sets a hyperlink on a style. This is useful for rendering text that
+// can be clicked on in a terminal emulator that supports hyperlinks.
+//
+// Example:
+//
+// s := lipgloss.NewStyle().Hyperlink("https://charm.sh")
+// s := lipgloss.NewStyle().Hyperlink("https://charm.sh", "id=1")
+func (s Style) Hyperlink(link string, params ...string) Style {
+ s.set(linkKey, link)
+ if len(params) > 0 {
+ s.set(linkParamsKey, strings.Join(params, ":"))
+ }
return s
}
@@ -768,7 +901,7 @@ func whichSidesBool(i ...bool) (top, right, bottom, left bool, ok bool) {
// whichSidesColor is like whichSides, except it operates on a series of
// boolean values. See the comment on whichSidesInt for details on how this
// works.
-func whichSidesColor(i ...TerminalColor) (top, right, bottom, left TerminalColor, ok bool) {
+func whichSidesColor(i ...color.Color) (top, right, bottom, left color.Color, ok bool) {
switch len(i) {
case 1:
top = i[0]
diff --git a/vendor/github.com/charmbracelet/lipgloss/size.go b/vendor/charm.land/lipgloss/v2/size.go
similarity index 75%
rename from vendor/github.com/charmbracelet/lipgloss/size.go
rename to vendor/charm.land/lipgloss/v2/size.go
index e169ff5e..e0384d03 100644
--- a/vendor/github.com/charmbracelet/lipgloss/size.go
+++ b/vendor/charm.land/lipgloss/v2/size.go
@@ -10,10 +10,10 @@ import (
// ignored and characters wider than one cell (such as Chinese characters and
// emojis) are appropriately measured.
//
-// You should use this instead of len(string) len([]rune(string) as neither
+// You should use this instead of len(string) or len([]rune(string) as neither
// will give you accurate results.
func Width(str string) (width int) {
- for _, l := range strings.Split(str, "\n") {
+ for l := range strings.SplitSeq(str, "\n") {
w := ansi.StringWidth(l)
if w > width {
width = w
@@ -24,9 +24,8 @@ func Width(str string) (width int) {
}
// Height returns height of a string in cells. This is done simply by
-// counting \n characters. If your strings use \r\n for newlines you should
-// convert them to \n first, or simply write a separate function for measuring
-// height.
+// counting \n characters. If your output has \r\n, that sequence will be
+// replaced with a \n in [Style.Render].
func Height(str string) int {
return strings.Count(str, "\n") + 1
}
diff --git a/vendor/github.com/charmbracelet/lipgloss/style.go b/vendor/charm.land/lipgloss/v2/style.go
similarity index 68%
rename from vendor/github.com/charmbracelet/lipgloss/style.go
rename to vendor/charm.land/lipgloss/v2/style.go
index 59fa3ab2..3cd65952 100644
--- a/vendor/github.com/charmbracelet/lipgloss/style.go
+++ b/vendor/charm.land/lipgloss/v2/style.go
@@ -1,15 +1,18 @@
package lipgloss
import (
+ "image/color"
"strings"
"unicode"
"github.com/charmbracelet/x/ansi"
- "github.com/charmbracelet/x/cellbuf"
- "github.com/muesli/termenv"
)
-const tabWidthDefault = 4
+const (
+ // NBSP is the non-breaking space rune.
+ NBSP = '\u00A0'
+ tabWidthDefault = 4
+)
// Property for a key.
type propKey int64
@@ -19,7 +22,6 @@ const (
// Boolean props come first.
boldKey propKey = 1 << iota
italicKey
- underlineKey
strikethroughKey
reverseKey
blinkKey
@@ -29,8 +31,10 @@ const (
colorWhitespaceKey
// Non-boolean props.
+ underlineKey
foregroundKey
backgroundKey
+ underlineColorKey
widthKey
heightKey
alignHorizontalKey
@@ -41,6 +45,7 @@ const (
paddingRightKey
paddingBottomKey
paddingLeftKey
+ paddingCharKey
// Margins.
marginTopKey
@@ -48,6 +53,7 @@ const (
marginBottomKey
marginLeftKey
marginBackgroundKey
+ marginCharKey
// Border runes.
borderStyleKey
@@ -63,6 +69,8 @@ const (
borderRightForegroundKey
borderBottomForegroundKey
borderLeftForegroundKey
+ borderForegroundBlendKey
+ borderForegroundBlendOffsetKey
// Border background colors.
borderTopBackgroundKey
@@ -76,6 +84,10 @@ const (
tabWidthKey
transformKey
+
+ // Hyperlink.
+ linkKey
+ linkParamsKey
)
// props is a set of properties.
@@ -96,35 +108,53 @@ func (p props) has(k propKey) bool {
return p&props(k) != 0
}
-// NewStyle returns a new, empty Style. While it's syntactic sugar for the
-// Style{} primitive, it's recommended to use this function for creating styles
-// in case the underlying implementation changes. It takes an optional string
-// value to be set as the underlying string value for this style.
-func NewStyle() Style {
- return renderer.NewStyle()
-}
+// Underline is the style of the underline.
+//
+// Caveats:
+// - Not all terminals support all underline styles.
+// - Some terminals may render unsupported styles as standard underlines.
+// - Terminal themes may affect the visibility of different underline styles.
+type Underline = ansi.Underline
+
+const (
+ // UnderlineNone is no underline.
+ UnderlineNone = ansi.UnderlineNone
+ // UnderlineSingle is a single underline. This is the default when underline is enabled.
+ UnderlineSingle = ansi.UnderlineSingle
+ // UnderlineDouble is a double underline.
+ UnderlineDouble = ansi.UnderlineDouble
+ // UnderlineCurly is a curly underline.
+ UnderlineCurly = ansi.UnderlineCurly
+ // UnderlineDotted is a dotted underline.
+ UnderlineDotted = ansi.UnderlineDotted
+ // UnderlineDashed is a dashed underline.
+ UnderlineDashed = ansi.UnderlineDashed
+)
// NewStyle returns a new, empty Style. While it's syntactic sugar for the
-// Style{} primitive, it's recommended to use this function for creating styles
-// in case the underlying implementation changes. It takes an optional string
-// value to be set as the underlying string value for this style.
-func (r *Renderer) NewStyle() Style {
- s := Style{r: r}
- return s
+// [Style]{} primitive, it's recommended to use this function for creating styles
+// in case the underlying implementation changes.
+func NewStyle() Style {
+ return Style{}
}
// Style contains a set of rules that comprise a style as a whole.
type Style struct {
- r *Renderer
props props
value string
+ // hyperlink
+ link, linkParams string
+
// we store bool props values here
attrs int
// props that have values
- fgColor TerminalColor
- bgColor TerminalColor
+ fgColor color.Color
+ bgColor color.Color
+ ulColor color.Color
+
+ ul Underline
width int
height int
@@ -136,22 +166,26 @@ type Style struct {
paddingRight int
paddingBottom int
paddingLeft int
+ paddingChar rune
marginTop int
marginRight int
marginBottom int
marginLeft int
- marginBgColor TerminalColor
-
- borderStyle Border
- borderTopFgColor TerminalColor
- borderRightFgColor TerminalColor
- borderBottomFgColor TerminalColor
- borderLeftFgColor TerminalColor
- borderTopBgColor TerminalColor
- borderRightBgColor TerminalColor
- borderBottomBgColor TerminalColor
- borderLeftBgColor TerminalColor
+ marginBgColor color.Color
+ marginChar rune
+
+ borderStyle Border
+ borderTopFgColor color.Color
+ borderRightFgColor color.Color
+ borderBottomFgColor color.Color
+ borderLeftFgColor color.Color
+ borderBlendFgColor []color.Color
+ borderForegroundBlendOffset int
+ borderTopBgColor color.Color
+ borderRightBgColor color.Color
+ borderBottomBgColor color.Color
+ borderLeftBgColor color.Color
maxWidth int
maxHeight int
@@ -167,10 +201,10 @@ func joinString(strs ...string) string {
}
// SetString sets the underlying string value for this style. To render once
-// the underlying string is set, use the Style.String. This method is
+// the underlying string is set, use the [Style.String]. This method is
// a convenience for cases when having a stringer implementation is handy, such
// as when using fmt.Sprintf. You can also simply define a style and render out
-// strings directly with Style.Render.
+// strings directly with [Style.Render].
func (s Style) SetString(strs ...string) Style {
s.value = joinString(strs...)
return s
@@ -232,9 +266,6 @@ func (s Style) Inherit(i Style) Style {
// Render applies the defined style formatting to a given string.
func (s Style) Render(strs ...string) string {
- if s.r == nil {
- s.r = renderer
- }
if s.value != "" {
strs = append([]string{s.value}, strs...)
}
@@ -242,14 +273,12 @@ func (s Style) Render(strs ...string) string {
var (
str = joinString(strs...)
- p = s.r.ColorProfile()
- te = p.String()
- teSpace = p.String()
- teWhitespace = p.String()
+ te ansi.Style
+ teSpace ansi.Style
+ teWhitespace ansi.Style
bold = s.getAsBool(boldKey, false)
italic = s.getAsBool(italicKey, false)
- underline = s.getAsBool(underlineKey, false)
strikethrough = s.getAsBool(strikethroughKey, false)
reverse = s.getAsBool(reverseKey, false)
blink = s.getAsBool(blinkKey, false)
@@ -257,7 +286,9 @@ func (s Style) Render(strs ...string) string {
fg = s.getAsColor(foregroundKey)
bg = s.getAsColor(backgroundKey)
+ ul = s.getAsColor(underlineColorKey)
+ underline = s.ul != UnderlineNone
width = s.getAsInt(widthKey)
height = s.getAsInt(heightKey)
horizontalAlign = s.getAsPosition(alignHorizontalKey)
@@ -268,6 +299,9 @@ func (s Style) Render(strs ...string) string {
bottomPadding = s.getAsInt(paddingBottomKey)
leftPadding = s.getAsInt(paddingLeftKey)
+ horizontalBorderSize = s.GetHorizontalBorderSize()
+ verticalBorderSize = s.GetVerticalBorderSize()
+
colorWhitespace = s.getAsBool(colorWhitespaceKey, true)
inline = s.getAsBool(inlineKey, false)
maxWidth = s.getAsInt(maxWidthKey)
@@ -284,6 +318,8 @@ func (s Style) Render(strs ...string) string {
useSpaceStyler = (underline && !underlineSpaces) || (strikethrough && !strikethroughSpaces) || underlineSpaces || strikethroughSpaces
transform = s.getAsTransform(transformKey)
+
+ link, linkParams = s.GetHyperlink()
)
if transform != nil {
@@ -294,62 +330,68 @@ func (s Style) Render(strs ...string) string {
return s.maybeConvertTabs(str)
}
- // Enable support for ANSI on the legacy Windows cmd.exe console. This is a
- // no-op on non-Windows systems and on Windows runs only once.
- enableLegacyWindowsANSI()
-
if bold {
te = te.Bold()
}
if italic {
- te = te.Italic()
+ te = te.Italic(true)
}
if underline {
- te = te.Underline()
+ te = te.Underline(true)
}
if reverse {
- teWhitespace = teWhitespace.Reverse()
- te = te.Reverse()
+ teWhitespace = teWhitespace.Reverse(true)
+ te = te.Reverse(true)
}
if blink {
- te = te.Blink()
+ te = te.Blink(true)
}
if faint {
te = te.Faint()
}
if fg != noColor {
- te = te.Foreground(fg.color(s.r))
+ te = te.ForegroundColor(fg)
if styleWhitespace {
- teWhitespace = teWhitespace.Foreground(fg.color(s.r))
+ teWhitespace = teWhitespace.ForegroundColor(fg)
}
if useSpaceStyler {
- teSpace = teSpace.Foreground(fg.color(s.r))
+ teSpace = teSpace.ForegroundColor(fg)
}
}
if bg != noColor {
- te = te.Background(bg.color(s.r))
+ te = te.BackgroundColor(bg)
+ if colorWhitespace {
+ teWhitespace = teWhitespace.BackgroundColor(bg)
+ }
+ if useSpaceStyler {
+ teSpace = teSpace.BackgroundColor(bg)
+ }
+ }
+
+ if ul != noColor {
+ te = te.UnderlineColor(ul)
if colorWhitespace {
- teWhitespace = teWhitespace.Background(bg.color(s.r))
+ teWhitespace = teWhitespace.UnderlineColor(ul)
}
if useSpaceStyler {
- teSpace = teSpace.Background(bg.color(s.r))
+ teSpace = teSpace.UnderlineColor(ul)
}
}
if underline {
- te = te.Underline()
+ te = te.UnderlineStyle(s.ul)
}
if strikethrough {
- te = te.CrossOut()
+ te = te.Strikethrough(true)
}
if underlineSpaces {
- teSpace = teSpace.Underline()
+ teSpace = teSpace.Underline(true)
}
if strikethroughSpaces {
- teSpace = teSpace.CrossOut()
+ teSpace = teSpace.Strikethrough(true)
}
// Potentially convert tabs to spaces
@@ -362,21 +404,30 @@ func (s Style) Render(strs ...string) string {
str = strings.ReplaceAll(str, "\n", "")
}
+ // Include borders in block size.
+ width -= horizontalBorderSize
+ height -= verticalBorderSize
+
// Word wrap
if !inline && width > 0 {
wrapAt := width - leftPadding - rightPadding
- str = cellbuf.Wrap(str, wrapAt, "")
+ str = Wrap(str, wrapAt, "")
}
// Render core text
{
var b strings.Builder
- l := strings.Split(str, "\n")
- for i := range l {
+ isFirst := true
+ for line := range strings.SplitSeq(str, "\n") {
+ if isFirst {
+ isFirst = false
+ } else {
+ b.WriteRune('\n')
+ }
if useSpaceStyler {
// Look for spaces and apply a different styler
- for _, r := range l[i] {
+ for _, r := range line {
if unicode.IsSpace(r) {
b.WriteString(teSpace.Styled(string(r)))
continue
@@ -384,32 +435,37 @@ func (s Style) Render(strs ...string) string {
b.WriteString(te.Styled(string(r)))
}
} else {
- b.WriteString(te.Styled(l[i]))
- }
- if i != len(l)-1 {
- b.WriteRune('\n')
+ b.WriteString(te.Styled(line))
}
}
str = b.String()
+
+ if len(link) > 0 {
+ str = ansi.SetHyperlink(link, linkParams) + str + ansi.ResetHyperlink()
+ }
}
// Padding
if !inline { //nolint:nestif
+ padChar := s.paddingChar
+ if padChar == 0 {
+ padChar = ' '
+ }
if leftPadding > 0 {
- var st *termenv.Style
+ var st *ansi.Style
if colorWhitespace || styleWhitespace {
st = &teWhitespace
}
- str = padLeft(str, leftPadding, st)
+ str = padLeft(str, leftPadding, st, padChar)
}
if rightPadding > 0 {
- var st *termenv.Style
+ var st *ansi.Style
if colorWhitespace || styleWhitespace {
st = &teWhitespace
}
- str = padRight(str, rightPadding, st)
+ str = padRight(str, rightPadding, st, padChar)
}
if topPadding > 0 {
@@ -433,7 +489,7 @@ func (s Style) Render(strs ...string) string {
numLines := strings.Count(str, "\n")
if numLines != 0 || width != 0 {
- var st *termenv.Style
+ var st *ansi.Style
if colorWhitespace || styleWhitespace {
st = &teWhitespace
}
@@ -491,17 +547,21 @@ func (s Style) applyMargins(str string, inline bool) string {
bottomMargin = s.getAsInt(marginBottomKey)
leftMargin = s.getAsInt(marginLeftKey)
- styler termenv.Style
+ style ansi.Style
)
bgc := s.getAsColor(marginBackgroundKey)
if bgc != noColor {
- styler = styler.Background(bgc.color(s.r))
+ style = style.BackgroundColor(bgc)
}
// Add left and right margin
- str = padLeft(str, leftMargin, &styler)
- str = padRight(str, rightMargin, &styler)
+ marginChar := s.marginChar
+ if marginChar == 0 {
+ marginChar = ' '
+ }
+ str = padLeft(str, leftMargin, &style, marginChar)
+ str = padRight(str, rightMargin, &style, marginChar)
// Top/bottom margin
if !inline {
@@ -509,10 +569,10 @@ func (s Style) applyMargins(str string, inline bool) string {
spaces := strings.Repeat(" ", width)
if topMargin > 0 {
- str = styler.Styled(strings.Repeat(spaces+"\n", topMargin)) + str
+ str = style.Styled(strings.Repeat(spaces+"\n", topMargin)) + str
}
if bottomMargin > 0 {
- str += styler.Styled(strings.Repeat("\n"+spaces, bottomMargin))
+ str += style.Styled(strings.Repeat("\n"+spaces, bottomMargin))
}
}
@@ -520,65 +580,54 @@ func (s Style) applyMargins(str string, inline bool) string {
}
// Apply left padding.
-func padLeft(str string, n int, style *termenv.Style) string {
- return pad(str, -n, style)
+func padLeft(str string, n int, style *ansi.Style, r rune) string {
+ return pad(str, -n, style, r)
}
// Apply right padding.
-func padRight(str string, n int, style *termenv.Style) string {
- return pad(str, n, style)
+func padRight(str string, n int, style *ansi.Style, r rune) string {
+ return pad(str, n, style, r)
}
// pad adds padding to either the left or right side of a string.
// Positive values add to the right side while negative values
// add to the left side.
-func pad(str string, n int, style *termenv.Style) string {
+// r is the rune to use for padding. We use " " for margins and
+// "\u00A0" for padding so that the padding is preserved when the
+// string is copied and pasted.
+func pad(str string, n int, style *ansi.Style, r rune) string {
if n == 0 {
return str
}
- sp := strings.Repeat(" ", abs(n))
+ sp := strings.Repeat(string(r), abs(n))
if style != nil {
sp = style.Styled(sp)
}
b := strings.Builder{}
- l := strings.Split(str, "\n")
-
- for i := range l {
+ isFirst := true
+ for line := range strings.SplitSeq(str, "\n") {
+ if isFirst {
+ isFirst = false
+ } else {
+ b.WriteRune('\n')
+ }
switch {
// pad right
case n > 0:
- b.WriteString(l[i])
+ b.WriteString(line)
b.WriteString(sp)
// pad left
default:
b.WriteString(sp)
- b.WriteString(l[i])
- }
-
- if i != len(l)-1 {
- b.WriteRune('\n')
+ b.WriteString(line)
}
}
return b.String()
}
-func max(a, b int) int { //nolint:unparam,predeclared
- if a > b {
- return a
- }
- return b
-}
-
-func min(a, b int) int { //nolint:predeclared
- if a < b {
- return a
- }
- return b
-}
-
func abs(a int) int {
if a < 0 {
return -a
diff --git a/vendor/charm.land/lipgloss/v2/terminal.go b/vendor/charm.land/lipgloss/v2/terminal.go
new file mode 100644
index 00000000..a336abc7
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/terminal.go
@@ -0,0 +1,124 @@
+package lipgloss
+
+import (
+ "fmt"
+ "image/color"
+ "io"
+ "strings"
+ "time"
+
+ uv "github.com/charmbracelet/ultraviolet"
+ "github.com/charmbracelet/x/ansi"
+)
+
+// queryBackgroundColor queries the terminal for the background color.
+// If the terminal does not support querying the background color, nil is
+// returned.
+//
+// Note: you will need to set the input to raw mode before calling this
+// function.
+//
+// state, _ := term.MakeRaw(in.Fd())
+// defer term.Restore(in.Fd(), state)
+//
+// copied from x/term@v0.1.3.
+func queryBackgroundColor(in io.Reader, out io.Writer) (c color.Color, err error) {
+ err = queryTerminal(in, out, defaultQueryTimeout,
+ func(seq string, pa *ansi.Parser) bool {
+ switch {
+ case ansi.HasOscPrefix(seq):
+ switch pa.Command() {
+ case 11: // OSC 11
+ parts := strings.Split(string(pa.Data()), ";")
+ if len(parts) != 2 {
+ break // invalid, but we still need to parse the next sequence
+ }
+ c = ansi.XParseColor(parts[1])
+ }
+ case ansi.HasCsiPrefix(seq):
+ switch pa.Command() {
+ case ansi.Command('?', 0, 'c'): // DA1
+ return false
+ }
+ }
+ return true
+ }, ansi.RequestBackgroundColor+ansi.RequestPrimaryDeviceAttributes)
+ return
+}
+
+const defaultQueryTimeout = time.Second * 2
+
+// queryTerminalFilter is a function that filters input events using a type
+// switch. If false is returned, the QueryTerminal function will stop reading
+// input.
+type queryTerminalFilter func(seq string, pa *ansi.Parser) bool
+
+// queryTerminal queries the terminal for support of various features and
+// returns a list of response events.
+// Most of the time, you will need to set stdin to raw mode before calling this
+// function.
+// Note: This function will block until the terminal responds or the timeout
+// is reached.
+// copied from x/term@v0.1.3.
+func queryTerminal(
+ in io.Reader,
+ out io.Writer,
+ timeout time.Duration,
+ filter queryTerminalFilter,
+ query string,
+) error {
+ // We use [uv.NewCancelReader] because it uses a different Windows
+ // implementation than the on in the [cancelreader] library, which uses
+ // the Cancel IO API to cancel reads instead of using Overlapped IO.
+ rd, err := uv.NewCancelReader(in)
+ if err != nil {
+ return fmt.Errorf("could not create cancel reader: %w", err)
+ }
+
+ defer rd.Close() //nolint: errcheck
+
+ done := make(chan struct{}, 1)
+ defer close(done)
+ go func() {
+ select {
+ case <-done:
+ case <-time.After(timeout):
+ rd.Cancel()
+ }
+ }()
+
+ if _, err := io.WriteString(out, query); err != nil {
+ return fmt.Errorf("could not write query: %w", err)
+ }
+
+ pa := ansi.GetParser()
+ defer ansi.PutParser(pa)
+
+ var acc []byte // Accumulate partial responses before filtering
+ var buf [256]byte // 256 bytes should be enough for most responses
+ var state byte
+ for {
+ n, err := rd.Read(buf[:])
+ if err != nil {
+ return fmt.Errorf("could not read from input: %w", err)
+ }
+
+ p := buf[:]
+ for n > 0 {
+ seq, _, read, newState := ansi.DecodeSequence(p[:n], state, pa)
+ acc = append(acc, seq...)
+
+ if newState == ansi.NormalState {
+ if !filter(string(acc), pa) {
+ return nil
+ }
+
+ acc = acc[:0]
+ }
+
+ state = newState
+ n -= read
+ p = p[read:]
+ }
+ }
+}
diff --git a/vendor/github.com/charmbracelet/lipgloss/unset.go b/vendor/charm.land/lipgloss/v2/unset.go
similarity index 91%
rename from vendor/github.com/charmbracelet/lipgloss/unset.go
rename to vendor/charm.land/lipgloss/v2/unset.go
index 1086e722..b81ee882 100644
--- a/vendor/github.com/charmbracelet/lipgloss/unset.go
+++ b/vendor/charm.land/lipgloss/v2/unset.go
@@ -19,8 +19,7 @@ func (s Style) UnsetItalic() Style {
// UnsetUnderline removes the underline style rule, if set.
func (s Style) UnsetUnderline() Style {
- s.unset(underlineKey)
- return s
+ return s.Underline(false)
}
// UnsetStrikethrough removes the strikethrough style rule, if set.
@@ -96,6 +95,13 @@ func (s Style) UnsetPadding() Style {
s.unset(paddingRightKey)
s.unset(paddingTopKey)
s.unset(paddingBottomKey)
+ s.unset(paddingCharKey)
+ return s
+}
+
+// UnsetPaddingChar removes the padding character style rule, if set.
+func (s Style) UnsetPaddingChar() Style {
+ s.unset(paddingCharKey)
return s
}
@@ -237,6 +243,20 @@ func (s Style) UnsetBorderLeftForeground() Style {
return s
}
+// UnsetBorderForegroundBlend removes the border blend foreground color rules,
+// if set.
+func (s Style) UnsetBorderForegroundBlend() Style {
+ s.unset(borderForegroundBlendKey)
+ return s
+}
+
+// UnsetBorderForegroundBlendOffset removes the border blend offset style rule,
+// if set.
+func (s Style) UnsetBorderForegroundBlendOffset() Style {
+ s.unset(borderForegroundBlendOffsetKey)
+ return s
+}
+
// UnsetBorderBackground removes all border background color styles, if
// set.
func (s Style) UnsetBorderBackground() Style {
@@ -324,6 +344,14 @@ func (s Style) UnsetTransform() Style {
return s
}
+// UnsetHyperlink removes the value set by Hyperlink.
+func (s Style) UnsetHyperlink() Style {
+ s.unset(linkKey)
+ s.unset(linkParamsKey)
+ s.link, s.linkParams = "", "" // save memory
+ return s
+}
+
// UnsetString sets the underlying string value to the empty string.
func (s Style) UnsetString() Style {
s.value = ""
diff --git a/vendor/github.com/charmbracelet/lipgloss/whitespace.go b/vendor/charm.land/lipgloss/v2/whitespace.go
similarity index 55%
rename from vendor/github.com/charmbracelet/lipgloss/whitespace.go
rename to vendor/charm.land/lipgloss/v2/whitespace.go
index 040dc98e..e353a076 100644
--- a/vendor/github.com/charmbracelet/lipgloss/whitespace.go
+++ b/vendor/charm.land/lipgloss/v2/whitespace.go
@@ -4,24 +4,17 @@ import (
"strings"
"github.com/charmbracelet/x/ansi"
- "github.com/muesli/termenv"
)
// whitespace is a whitespace renderer.
type whitespace struct {
- re *Renderer
- style termenv.Style
chars string
+ style Style
}
-// newWhitespace creates a new whitespace renderer. The order of the options
-// matters, if you're using WithWhitespaceRenderer, make sure it comes first as
-// other options might depend on it.
-func newWhitespace(r *Renderer, opts ...WhitespaceOption) *whitespace {
- w := &whitespace{
- re: r,
- style: r.ColorProfile().String(),
- }
+// newWhitespace creates a new whitespace renderer.
+func newWhitespace(opts ...WhitespaceOption) *whitespace {
+ w := &whitespace{}
for _, opt := range opts {
opt(w)
}
@@ -41,11 +34,18 @@ func (w whitespace) render(width int) string {
// Cycle through runes and print them into the whitespace.
for i := 0; i < width; {
b.WriteRune(r[j])
+ // Measure the width of the rune we just wrote, ensuring we always
+ // make progress to avoid infinite loops with zero-width characters
+ // like tabs.
+ runeWidth := ansi.StringWidth(string(r[j]))
+ if runeWidth < 1 {
+ runeWidth = 1
+ }
+ i += runeWidth
j++
if j >= len(r) {
j = 0
}
- i += ansi.StringWidth(string(r[j]))
}
// Fill any extra gaps white spaces. This might be necessary if any runes
@@ -55,23 +55,16 @@ func (w whitespace) render(width int) string {
b.WriteString(strings.Repeat(" ", short))
}
- return w.style.Styled(b.String())
+ return w.style.Render(b.String())
}
// WhitespaceOption sets a styling rule for rendering whitespace.
type WhitespaceOption func(*whitespace)
-// WithWhitespaceForeground sets the color of the characters in the whitespace.
-func WithWhitespaceForeground(c TerminalColor) WhitespaceOption {
- return func(w *whitespace) {
- w.style = w.style.Foreground(c.color(w.re))
- }
-}
-
-// WithWhitespaceBackground sets the background color of the whitespace.
-func WithWhitespaceBackground(c TerminalColor) WhitespaceOption {
+// WithWhitespaceStyle sets the style for the whitespace.
+func WithWhitespaceStyle(s Style) WhitespaceOption {
return func(w *whitespace) {
- w.style = w.style.Background(c.color(w.re))
+ w.style = s
}
}
diff --git a/vendor/charm.land/lipgloss/v2/wrap.go b/vendor/charm.land/lipgloss/v2/wrap.go
new file mode 100644
index 00000000..ccffe89b
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/wrap.go
@@ -0,0 +1,113 @@
+package lipgloss
+
+import (
+ "bytes"
+ "io"
+
+ uv "github.com/charmbracelet/ultraviolet"
+ "github.com/charmbracelet/x/ansi"
+)
+
+// Wrap wraps the given string to the given width, preserving ANSI styles and links.
+func Wrap(s string, width int, breakpoints string) string {
+ var buf bytes.Buffer
+ s = ansi.Wrap(s, width, breakpoints)
+ w := NewWrapWriter(&buf)
+ defer w.Close() //nolint:errcheck
+ _, _ = io.WriteString(w, s)
+ return buf.String()
+}
+
+// WrapWriter is a writer that writes to a buffer and keeps track of the
+// current pen style and link state for the purpose of wrapping with newlines.
+//
+// When it encounters a newline, it resets the style and link, writes the
+// newline, and then reapplies the style and link to the next line.
+type WrapWriter struct {
+ w io.Writer
+ p *ansi.Parser
+ style uv.Style
+ link uv.Link
+}
+
+// NewWrapWriter returns a new [WrapWriter].
+func NewWrapWriter(w io.Writer) *WrapWriter {
+ pw := &WrapWriter{w: w}
+ pw.p = ansi.GetParser()
+ handleCsi := func(cmd ansi.Cmd, params ansi.Params) {
+ if cmd == 'm' {
+ uv.ReadStyle(params, &pw.style)
+ }
+ }
+ handleOsc := func(cmd int, data []byte) {
+ if cmd == 8 {
+ uv.ReadLink(data, &pw.link)
+ }
+ }
+ pw.p.SetHandler(ansi.Handler{
+ HandleCsi: handleCsi,
+ HandleOsc: handleOsc,
+ })
+ return pw
+}
+
+// Style returns the current pen style.
+func (w *WrapWriter) Style() uv.Style {
+ return w.style
+}
+
+// Link returns the current pen link.
+func (w *WrapWriter) Link() uv.Link {
+ return w.link
+}
+
+// Write writes to the buffer.
+func (w *WrapWriter) Write(p []byte) (int, error) {
+ if w.p == nil {
+ // The writer has been closed and its parser returned to the pool.
+ // Writing after close can happen during out-of-order teardown of
+ // nested writer chains; treat it as a no-op rather than panicking.
+ return len(p), nil
+ }
+ for i := range p {
+ b := p[i]
+ w.p.Advance(b)
+ if b == '\n' {
+ if !w.style.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.ResetStyle))
+ }
+ if !w.link.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.ResetHyperlink()))
+ }
+ }
+
+ _, _ = w.w.Write([]byte{b})
+ if b == '\n' {
+ if !w.link.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.SetHyperlink(w.link.URL, w.link.Params)))
+ }
+ if !w.style.IsZero() {
+ _, _ = w.w.Write([]byte(w.style.String()))
+ }
+ }
+ }
+
+ return len(p), nil
+}
+
+// Close closes the writer, resets the style and link if necessary, and releases
+// its parser. Calling it is performance critical, but forgetting it does not
+// cause safety issues or leaks.
+func (w *WrapWriter) Close() error {
+ if !w.style.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.ResetStyle))
+ }
+ if !w.link.IsZero() {
+ _, _ = w.w.Write([]byte(ansi.ResetHyperlink()))
+ }
+ if w.p != nil {
+ ansi.PutParser(w.p)
+ w.p = nil
+ }
+ return nil
+}
diff --git a/vendor/charm.land/lipgloss/v2/writer.go b/vendor/charm.land/lipgloss/v2/writer.go
new file mode 100644
index 00000000..78b48b8d
--- /dev/null
+++ b/vendor/charm.land/lipgloss/v2/writer.go
@@ -0,0 +1,160 @@
+package lipgloss
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+
+ "github.com/charmbracelet/colorprofile"
+)
+
+// Writer is the default writer that prints to stdout, automatically
+// downsampling colors when necessary.
+var Writer = colorprofile.NewWriter(os.Stdout, os.Environ())
+
+// Println to stdout, automatically downsampling colors when necessary, ending
+// with a trailing newline.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("breakfast")
+//
+// Println("Time for a", str, "sandwich!")
+func Println(v ...any) (int, error) {
+ return fmt.Fprintln(Writer, v...) //nolint:wrapcheck
+}
+
+// Printf prints formatted text to stdout, automatically downsampling colors
+// when necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("knuckle")
+//
+// Printf("Time for a %s sandwich!\n", str)
+func Printf(format string, v ...any) (int, error) {
+ return fmt.Fprintf(Writer, format, v...) //nolint:wrapcheck
+}
+
+// Print to stdout, automatically downsampling colors when necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("Who wants marmalade?\n")
+//
+// Print(str)
+func Print(v ...any) (int, error) {
+ return fmt.Fprint(Writer, v...) //nolint:wrapcheck
+}
+
+// Fprint pritnts to the given writer, automatically downsampling colors when
+// necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("guzzle")
+//
+// Fprint(os.Stderr, "I %s horchata pretty much all the time.\n", str)
+func Fprint(w io.Writer, v ...any) (int, error) {
+ return fmt.Fprint(colorprofile.NewWriter(w, os.Environ()), v...) //nolint:wrapcheck
+}
+
+// Fprintln prints to the given writer, automatically downsampling colors when
+// necessary, and ending with a trailing newline.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("Sandwich time!")
+//
+// Fprintln(os.Stderr, str)
+func Fprintln(w io.Writer, v ...any) (int, error) {
+ return fmt.Fprintln(colorprofile.NewWriter(w, os.Environ()), v...) //nolint:wrapcheck
+}
+
+// Fprintf prints text to a writer, against the given format, automatically
+// downsampling colors when necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("artichokes")
+//
+// Fprintf(os.Stderr, "I really love %s!\n", food)
+func Fprintf(w io.Writer, format string, v ...any) (int, error) {
+ return fmt.Fprintf(colorprofile.NewWriter(w, os.Environ()), format, v...) //nolint:wrapcheck
+}
+
+// Sprint returns a string for stdout, automatically downsampling colors when
+// necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Faint(true).
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("I love to eat")
+//
+// str = Sprint(str)
+func Sprint(v ...any) string {
+ var buf bytes.Buffer
+ w := colorprofile.Writer{
+ Forward: &buf,
+ Profile: Writer.Profile,
+ }
+ fmt.Fprint(&w, v...) //nolint:errcheck
+ return buf.String()
+}
+
+// Sprintln returns a string for stdout, automatically downsampling colors when
+// necessary, and ending with a trailing newline.
+//
+// Example:
+//
+// str := NewStyle().
+// Bold(true).
+// Foreground(lipgloss.Color("#6a00ff")).
+// Render("Yummy!")
+//
+// str = Sprintln(str)
+func Sprintln(v ...any) string {
+ var buf bytes.Buffer
+ w := colorprofile.Writer{
+ Forward: &buf,
+ Profile: Writer.Profile,
+ }
+ fmt.Fprintln(&w, v...) //nolint:errcheck
+ return buf.String()
+}
+
+// Sprintf returns a formatted string for stdout, automatically downsampling
+// colors when necessary.
+//
+// Example:
+//
+// str := NewStyle().
+// Bold(true).
+// Foreground(lipgloss.Color("#fccaee")).
+// Render("Cantaloupe")
+//
+// str = Sprintf("I really love %s!", str)
+func Sprintf(format string, v ...any) string {
+ var buf bytes.Buffer
+ w := colorprofile.Writer{
+ Forward: &buf,
+ Profile: Writer.Profile,
+ }
+ fmt.Fprintf(&w, format, v...) //nolint:errcheck
+ return buf.String()
+}
diff --git a/vendor/github.com/muesli/termenv/LICENSE b/vendor/dev.gaijin.team/go/exhaustruct/v5/LICENSE
similarity index 96%
rename from vendor/github.com/muesli/termenv/LICENSE
rename to vendor/dev.gaijin.team/go/exhaustruct/v5/LICENSE
index 8532c45c..6698196c 100644
--- a/vendor/github.com/muesli/termenv/LICENSE
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2019 Christian Muehlhaeuser
+Copyright (c) 2022 Gaijin Entertainment
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/analyzer.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/analyzer.go
new file mode 100644
index 00000000..ef1bc9c5
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/analyzer.go
@@ -0,0 +1,112 @@
+package analyzer
+
+import (
+ "flag"
+ "sync"
+
+ "dev.gaijin.team/go/golib/e"
+ "dev.gaijin.team/go/golib/fields"
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+
+ "dev.gaijin.team/go/exhaustruct/v5/internal/astutil"
+ "dev.gaijin.team/go/exhaustruct/v5/internal/directive"
+ "dev.gaijin.team/go/exhaustruct/v5/internal/pattern"
+ "dev.gaijin.team/go/exhaustruct/v5/internal/structure"
+)
+
+// NewAnalyzer returns an analyzer configured exclusively through command-line
+// flags, intended for CLI drivers (singlechecker, go vet -vettool). The
+// processor is built lazily on the first run, after the driver has parsed the
+// flags.
+func NewAnalyzer() *analysis.Analyzer {
+ config := &Config{}
+
+ lazyProcessor := sync.OnceValues(func() (*structure.Processor, error) {
+ return newProcessor(config)
+ })
+
+ a := newBaseAnalyzer(func(pass *analysis.Pass) (any, error) {
+ processor, err := lazyProcessor()
+ if err != nil {
+ return nil, err
+ }
+
+ run(pass, config, processor)
+
+ return nil, nil //nolint:nilnil
+ })
+
+ a.Flags.Init("", flag.PanicOnError)
+ config.bindToFlagSet(&a.Flags)
+
+ return a
+}
+
+// NewAnalyzerWithConfig returns an analyzer configured programmatically,
+// intended for library consumers such as golangci-lint. The configuration is
+// copied and validated immediately; it exposes no flags, and later mutations
+// of the passed Config have no effect.
+func NewAnalyzerWithConfig(config Config) (*analysis.Analyzer, error) {
+ processor, err := newProcessor(&config)
+ if err != nil {
+ return nil, err
+ }
+
+ return newBaseAnalyzer(func(pass *analysis.Pass) (any, error) {
+ run(pass, &config, processor)
+
+ return nil, nil //nolint:nilnil
+ }), nil
+}
+
+func newBaseAnalyzer(run func(*analysis.Pass) (any, error)) *analysis.Analyzer {
+ return &analysis.Analyzer{ //nolint:exhaustruct
+ Name: "exhaustruct",
+ Doc: "Checks if all structure fields are initialized",
+ Run: run,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ }
+}
+
+func newProcessor(config *Config) (*structure.Processor, error) {
+ enforce, err := pattern.NewList(config.EnforcePatterns...)
+ if err != nil {
+ return nil, e.NewFrom("compile enforce patterns", err, fields.F("flag", "enforce-rx"))
+ }
+
+ ignore, err := pattern.NewList(config.IgnorePatterns...)
+ if err != nil {
+ return nil, e.NewFrom("compile ignore patterns", err, fields.F("flag", "ignore-rx"))
+ }
+
+ optional, err := pattern.NewList(config.OptionalPatterns...)
+ if err != nil {
+ return nil, e.NewFrom("compile optional patterns", err, fields.F("flag", "optional-rx"))
+ }
+
+ allowEmpty, err := pattern.NewList(config.AllowEmptyPatterns...)
+ if err != nil {
+ return nil, e.NewFrom("compile allow-empty patterns", err, fields.F("flag", "allow-empty-rx"))
+ }
+
+ fp := astutil.NewFileParser()
+
+ return structure.NewProcessor(
+ directive.NewScanner(fp),
+ structure.NewOriginScanner(fp),
+ structure.WithEnforce(enforce),
+ structure.WithIgnore(ignore),
+ structure.WithOptional(optional),
+ structure.WithAllowEmpty(allowEmpty),
+ ), nil
+}
+
+func run(pass *analysis.Pass, config *Config, processor *structure.Processor) {
+ for _, diag := range processor.Directives().ProcessFiles(pass.Fset, pass.Files...) {
+ pass.Report(diag)
+ }
+
+ newMissingFieldsVisitor(pass, config, processor).run()
+ runTagMigration(pass)
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/config.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/config.go
new file mode 100644
index 00000000..82101bc3
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/config.go
@@ -0,0 +1,134 @@
+package analyzer
+
+import (
+ "flag"
+ "strings"
+
+ "dev.gaijin.team/go/exhaustruct/v5/internal/pattern"
+)
+
+type Config struct {
+ // EnforcePatterns is a list of regular expressions to match type names that
+ // should be checked. Anonymous structs can be matched by '' alias.
+ //
+ // Each regular expression must match the full type name, including package path.
+ // For example, to match type `net/http.Cookie` regular expression should be
+ // `.*/http\.Cookie`, but not `http\.Cookie`.
+ EnforcePatterns Patterns `exhaustruct:"optional"`
+
+ // IgnorePatterns is a list of regular expressions to match type names that
+ // should be skipped from checking. Anonymous structs can be matched by
+ // '' alias.
+ //
+ // Has precedence over EnforcePatterns.
+ //
+ // Each regular expression must match the full type name, including package path.
+ // For example, to match type `net/http.Cookie` regular expression should be
+ // `.*/http\.Cookie`, but not `http\.Cookie`.
+ IgnorePatterns Patterns `exhaustruct:"optional"`
+
+ // OptionalPatterns is a list of regular expressions to match type names where
+ // all fields are treated as optional. Anonymous structs can be matched by
+ // '' alias.
+ //
+ // Each regular expression must match the full type name, including package path.
+ // For example, to match type `net/http.Cookie` regular expression should be
+ // `.*/http\.Cookie`, but not `http\.Cookie`.
+ OptionalPatterns Patterns `exhaustruct:"optional"`
+
+ // AllowEmpty allows empty structures, effectively excluding them from the check.
+ AllowEmpty bool `exhaustruct:"optional"`
+
+ // AllowEmptyPatterns is a list of regular expressions to match type names that
+ // should be allowed to be empty. Anonymous structs can be matched by
+ // '' alias.
+ //
+ // Each regular expression must match the full type name, including package path.
+ // For example, to match type `net/http.Cookie` regular expression should be
+ // `.*/http\.Cookie`, but not `http\.Cookie`.
+ AllowEmptyPatterns Patterns `exhaustruct:"optional"`
+
+ // AllowEmptyReturns allows empty structures in return statements.
+ AllowEmptyReturns bool `exhaustruct:"optional"`
+
+ // AllowEmptyDeclarations allows empty structures in variable declarations.
+ AllowEmptyDeclarations bool `exhaustruct:"optional"`
+
+ // ReportFullTypePath enables full package path in error messages instead of
+ // short package name. This helps when configuring include/exclude patterns,
+ // as import aliases can make short names ambiguous.
+ ReportFullTypePath bool `exhaustruct:"optional"`
+
+ // ExplicitMode enables opt-in checking. When true, only types marked with
+ // //exhaustruct:enforce directive or matching enforce-rx patterns are checked.
+ ExplicitMode bool `exhaustruct:"optional"`
+}
+
+// bindToFlagSet binds the config fields to the provided flag set.
+func (c *Config) bindToFlagSet(fs *flag.FlagSet) {
+ fs.BoolVar(&c.ExplicitMode, "explicit", c.ExplicitMode,
+ "Enable explicit mode: only check types marked with //exhaustruct:enforce "+
+ "directive or matching -enforce-rx patterns")
+
+ fs.Var(&c.EnforcePatterns, "enforce-rx",
+ "Regular expression to match type names that should be checked. "+
+ "Anonymous structs can be matched by '' alias. "+
+ "Each regex must match the full type name including package path. "+
+ "Example: `.*/http\\.Cookie`. Can be used multiple times.")
+
+ fs.Var(&c.IgnorePatterns, "ignore-rx",
+ "Regular expression to skip type names from checking, has precedence over -enforce-rx. "+
+ "Anonymous structs can be matched by '' alias. "+
+ "Each regex must match the full type name including package path. "+
+ "Example: `.*/http\\.Cookie`. Can be used multiple times.")
+
+ fs.Var(&c.OptionalPatterns, "optional-rx",
+ "Regular expression to match type names where all fields are optional. "+
+ "Anonymous structs can be matched by '' alias. "+
+ "Each regex must match the full type name including package path. "+
+ "Example: `.*/http\\.Cookie`. Can be used multiple times.")
+
+ fs.BoolVar(&c.AllowEmpty, "allow-empty", c.AllowEmpty,
+ "Allow empty structures, effectively excluding them from the check")
+
+ fs.Var(&c.AllowEmptyPatterns, "allow-empty-rx",
+ "Regular expression to match type names that should be allowed to be empty. "+
+ "Anonymous structs can be matched by '' alias. "+
+ "Each regex must match the full type name including package path. "+
+ "Example: `.*/http\\.Cookie`. Can be used multiple times.")
+
+ fs.BoolVar(&c.AllowEmptyReturns, "allow-empty-returns", c.AllowEmptyReturns,
+ "Allow empty structures in return statements")
+
+ fs.BoolVar(&c.AllowEmptyDeclarations, "allow-empty-declarations", c.AllowEmptyDeclarations,
+ "Allow empty structures in variable declarations")
+
+ fs.BoolVar(&c.ReportFullTypePath, "report-full-type-path", c.ReportFullTypePath,
+ "Report full package path in error messages (e.g., 'net/http.Cookie' instead of 'http.Cookie'). "+
+ "Useful for identifying types when configuring enforce/ignore patterns.")
+}
+
+// Patterns is a list of regular expression patterns. It implements
+// flag.Value, validating each value as a regular expression at
+// flag-parse time so invalid patterns fail early.
+type Patterns []string
+
+// String returns the patterns joined with commas (flag.Value interface).
+func (p *Patterns) String() string {
+ if p == nil {
+ return ""
+ }
+
+ return strings.Join(*p, ",")
+}
+
+// Set validates and appends a pattern (flag.Value interface).
+func (p *Patterns) Set(value string) error {
+ if _, err := pattern.NewList(value); err != nil {
+ return err //nolint:wrapcheck
+ }
+
+ *p = append(*p, value)
+
+ return nil
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/missing-fields-visitor.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/missing-fields-visitor.go
new file mode 100644
index 00000000..558d8092
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/missing-fields-visitor.go
@@ -0,0 +1,381 @@
+package analyzer
+
+import (
+ "fmt"
+ "go/ast"
+ "go/token"
+ "go/types"
+ "slices"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+
+ "dev.gaijin.team/go/exhaustruct/v5/internal/directive"
+ "dev.gaijin.team/go/exhaustruct/v5/internal/structure"
+)
+
+// missingFieldsVisitor checks struct literals for missing field initializations.
+type missingFieldsVisitor struct {
+ pass *analysis.Pass
+ config *Config
+ processor *structure.Processor
+}
+
+func newMissingFieldsVisitor(
+ pass *analysis.Pass,
+ config *Config,
+ processor *structure.Processor,
+) *missingFieldsVisitor {
+ return &missingFieldsVisitor{
+ pass: pass,
+ config: config,
+ processor: processor,
+ }
+}
+
+func (v *missingFieldsVisitor) run() {
+ insp := v.pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) //nolint:forcetypeassert
+
+ insp.WithStack([]ast.Node{(*ast.CompositeLit)(nil)}, v.visit)
+}
+
+func (v *missingFieldsVisitor) visit(n ast.Node, push bool, stack []ast.Node) bool {
+ if !push {
+ return true
+ }
+
+ lit, ok := n.(*ast.CompositeLit)
+ if !ok {
+ return true
+ }
+
+ lv := literalVisitor{missingFieldsVisitor: v, lit: lit, stack: stack}
+ lv.process()
+
+ return true
+}
+
+// literalVisitor carries context for processing a single composite literal.
+type literalVisitor struct {
+ *missingFieldsVisitor
+
+ lit *ast.CompositeLit
+ stack []ast.Node
+}
+
+// literal holds resolved info for a struct literal being checked.
+type literal struct {
+ strct *structure.Struct
+ ignored bool
+ enforced bool
+}
+
+// shouldCheck implements checking decision priority.
+func (l literal) shouldCheck(explicitMode bool) bool {
+ if l.ignored {
+ return false
+ }
+
+ if l.enforced {
+ return true
+ }
+
+ if l.strct.IsIgnored() {
+ return false
+ }
+
+ if l.strct.IsEnforced() {
+ return true
+ }
+
+ return !explicitMode
+}
+
+func (lv literalVisitor) process() {
+ lit, ok := lv.resolveLiteral()
+ if !ok {
+ return
+ }
+
+ if len(lv.lit.Elts) == 0 && lv.checkEmptyAllowed(lit.strct) {
+ return
+ }
+
+ if pos, msg := lv.checkLiteral(lit); pos != nil {
+ lv.pass.Reportf(*pos, "%s", msg)
+ }
+}
+
+// resolveLiteral extracts struct type information from the composite literal,
+// retrieves cached metadata, and looks up directives.
+func (lv literalVisitor) resolveLiteral() (lit literal, ok bool) {
+ typeName, strct, pos := lv.resolveLiteralType()
+ if strct == nil {
+ return literal{}, false //nolint:exhaustruct
+ }
+
+ s, diags := lv.processor.ResolveStruct(
+ lv.pass.Fset, typeName, strct, pos, lv.pass.Pkg,
+ )
+
+ for _, diag := range diags {
+ lv.pass.Report(diag)
+ }
+
+ if s == nil {
+ return literal{}, false //nolint:exhaustruct
+ }
+
+ litPos := lv.pass.Fset.Position(lv.lit.Pos())
+ dirs, dirDiags := lv.processor.Directives().Lookup(lv.pass.Fset, litPos)
+
+ for _, d := range dirDiags {
+ lv.pass.Report(d)
+ }
+
+ return literal{
+ strct: s,
+ ignored: dirs.Contains(directive.Ignore),
+ enforced: dirs.Contains(directive.Enforce),
+ }, true
+}
+
+// resolveLiteralType resolves the composite literal's type and definition position.
+func (lv literalVisitor) resolveLiteralType() (name *types.TypeName, strct *types.Struct, pos token.Pos) {
+ typ := lv.pass.TypesInfo.TypeOf(lv.lit)
+
+ if ptr, ok := typ.(*types.Pointer); ok {
+ typ = ptr.Elem()
+ }
+
+ switch t := typ.(type) {
+ case *types.Alias:
+ name = t.Obj()
+ case *types.Named:
+ name = t.Obj()
+ }
+
+ typ = types.Unalias(typ)
+
+ switch t := typ.(type) {
+ case *types.Named:
+ var ok bool
+
+ if strct, ok = t.Underlying().(*types.Struct); !ok {
+ return nil, nil, token.NoPos
+ }
+
+ pos = name.Pos()
+
+ return name, strct, pos
+
+ case *types.Struct:
+ pos = lv.findAnonymousStructPos()
+
+ return name, t, pos
+
+ default:
+ return nil, nil, token.NoPos
+ }
+}
+
+// findAnonymousStructPos finds the position of the struct keyword for anonymous structs.
+func (lv literalVisitor) findAnonymousStructPos() token.Pos {
+ if lv.lit.Type != nil {
+ if st, ok := lv.lit.Type.(*ast.StructType); ok {
+ return st.Struct
+ }
+
+ return token.NoPos
+ }
+
+ for i := len(lv.stack) - 2; i >= 0; i-- { //nolint:mnd
+ switch parent := lv.stack[i].(type) {
+ case *ast.KeyValueExpr:
+ continue
+
+ case *ast.CompositeLit:
+ return structPosFromType(parent.Type)
+
+ default:
+ return token.NoPos
+ }
+ }
+
+ return token.NoPos
+}
+
+func structPosFromType(typ ast.Expr) token.Pos {
+ if typ == nil {
+ return token.NoPos
+ }
+
+ switch t := typ.(type) {
+ case *ast.ArrayType:
+ return structPosFromExpr(t.Elt)
+
+ case *ast.MapType:
+ return structPosFromExpr(t.Value)
+ }
+
+ return token.NoPos
+}
+
+func structPosFromExpr(expr ast.Expr) token.Pos {
+ if star, ok := expr.(*ast.StarExpr); ok {
+ expr = star.X
+ }
+
+ if st, ok := expr.(*ast.StructType); ok {
+ return st.Struct
+ }
+
+ return token.NoPos
+}
+
+func (lv literalVisitor) checkEmptyAllowed(s *structure.Struct) bool {
+ if lv.config.AllowEmpty {
+ return true
+ }
+
+ if s.AllowEmptyDecl {
+ return true
+ }
+
+ if ret, ok := lv.getParentReturnStmt(); ok {
+ if lv.config.AllowEmptyReturns {
+ return true
+ }
+
+ if lv.isErrorReturnStatement(ret) {
+ return true
+ }
+ }
+
+ if lv.isChildOfVariableDeclaration() && lv.config.AllowEmptyDeclarations {
+ return true
+ }
+
+ return false
+}
+
+func (lv literalVisitor) checkLiteral(lit literal) (*token.Pos, string) {
+ if !lit.shouldCheck(lv.config.ExplicitMode) {
+ return nil, ""
+ }
+
+ strct := lit.strct
+
+ missingFields := strct.SkippedFields(lv.lit, lv.pass.Pkg.Path())
+
+ if len(missingFields) == 0 {
+ return nil, ""
+ }
+
+ pos := lv.lit.Pos()
+
+ displayName := strct.PackageName + "." + strct.Name
+ if lv.config.ReportFullTypePath {
+ displayName = strct.FullPath
+ }
+
+ if len(missingFields) == 1 {
+ return &pos, fmt.Sprintf("%s is missing field %s", displayName, structure.FormatFieldNames(missingFields))
+ }
+
+ return &pos, fmt.Sprintf("%s is missing fields %s", displayName, structure.FormatFieldNames(missingFields))
+}
+
+func (lv literalVisitor) isChildOfVariableDeclaration() bool {
+ if len(lv.stack) < 2 { //nolint:mnd
+ return false
+ }
+
+ for i := len(lv.stack) - 1; i > 0; i-- {
+ parent := lv.stack[i-1]
+
+ switch p := parent.(type) {
+ case *ast.AssignStmt:
+ if p.Tok == token.DEFINE {
+ return true
+ }
+
+ case *ast.ValueSpec:
+ return true
+
+ case *ast.UnaryExpr:
+ if p.Op == token.AND {
+ continue
+ }
+
+ return false
+
+ default:
+ return false
+ }
+ }
+
+ return false
+}
+
+func (lv literalVisitor) getParentReturnStmt() (*ast.ReturnStmt, bool) {
+ if len(lv.stack) < 2 { //nolint:mnd
+ return nil, false
+ }
+
+ for i := len(lv.stack) - 1; i > 0; i-- {
+ parent := lv.stack[i-1]
+
+ switch p := parent.(type) {
+ case *ast.ReturnStmt:
+ return p, true
+
+ case *ast.UnaryExpr:
+ if p.Op == token.AND {
+ continue
+ }
+
+ return nil, false
+
+ default:
+ return nil, false
+ }
+ }
+
+ return nil, false
+}
+
+//nolint:forcetypeassert,gochecknoglobals
+var builtinErrorInterface = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
+
+func (lv literalVisitor) isErrorReturnStatement(n *ast.ReturnStmt) bool {
+ if len(n.Results) == 0 {
+ return false
+ }
+
+ for _, ri := range slices.Backward(n.Results) {
+ if ri == lv.lit {
+ continue
+ }
+
+ switch ri := ri.(type) {
+ case *ast.Ident:
+ if ri.Name == "nil" {
+ continue
+ }
+
+ case *ast.UnaryExpr:
+ if ri.X == lv.lit {
+ continue
+ }
+ }
+
+ resultType := lv.pass.TypesInfo.TypeOf(ri)
+ if resultType != nil && types.Implements(resultType, builtinErrorInterface) {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/tag-migration-visitor.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/tag-migration-visitor.go
new file mode 100644
index 00000000..7e75b668
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/analyzer/tag-migration-visitor.go
@@ -0,0 +1,111 @@
+package analyzer
+
+import (
+ "go/ast"
+ "reflect"
+ "regexp"
+ "strings"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+// runTagMigration scans struct definitions for deprecated exhaustruct tags
+// and emits migration diagnostics with suggested fixes, using inspector to
+// traverse StructType nodes efficiently.
+func runTagMigration(pass *analysis.Pass) {
+ insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) //nolint:forcetypeassert
+
+ insp.Preorder([]ast.Node{new(ast.StructType)}, func(n ast.Node) {
+ visitStructType(pass, n)
+ })
+}
+
+func visitStructType(pass *analysis.Pass, n ast.Node) {
+ st, ok := n.(*ast.StructType)
+ if !ok {
+ return
+ }
+
+ if st.Fields == nil {
+ return
+ }
+
+ for _, field := range st.Fields.List {
+ if field.Tag == nil {
+ continue
+ }
+
+ value, ok := parseExhaustructTag(field.Tag.Value)
+ if !ok {
+ continue
+ }
+
+ pass.Report(buildTagDiagnostic(field, value))
+ }
+}
+
+const exhaustructTagKey = "exhaustruct"
+
+// parseExhaustructTag extracts value from `exhaustruct:"value"` tag.
+// Returns ("", false) if tag not present.
+func parseExhaustructTag(tagLiteral string) (string, bool) {
+ if len(tagLiteral) < 2 { //nolint:mnd
+ return "", false
+ }
+
+ // Strip backticks
+ inner := tagLiteral[1 : len(tagLiteral)-1]
+
+ return reflect.StructTag(inner).Lookup(exhaustructTagKey)
+}
+
+func buildTagDiagnostic(field *ast.Field, tagValue string) analysis.Diagnostic {
+ return analysis.Diagnostic{
+ Pos: field.Tag.Pos(),
+ Message: `struct tag "exhaustruct" is not supported anymore, use comment directives`,
+ SuggestedFixes: []analysis.SuggestedFix{buildTagFix(field, tagValue)},
+ }
+}
+
+func buildTagFix(field *ast.Field, tagValue string) analysis.SuggestedFix {
+ tag := field.Tag
+ newTag := removeExhaustructFromTag(tag.Value)
+
+ if tagValue == "optional" {
+ if newTag != "" {
+ newTag += " "
+ }
+
+ newTag += "//exhaustruct:optional"
+ }
+
+ // Calculate start position (include leading space if removing entirely)
+ startPos := tag.Pos()
+ if newTag == "" {
+ startPos = field.Type.End()
+ }
+
+ return analysis.SuggestedFix{
+ Message: "fix",
+ TextEdits: []analysis.TextEdit{{
+ Pos: startPos,
+ End: tag.End(),
+ NewText: []byte(newTag),
+ }},
+ }
+}
+
+var exhaustructTagPattern = regexp.MustCompile(`\s*exhaustruct:"[^"]*"`)
+
+func removeExhaustructFromTag(tagLiteral string) string {
+ tagLiteral = tagLiteral[1 : len(tagLiteral)-1]
+ tagLiteral = strings.TrimSpace(exhaustructTagPattern.ReplaceAllString(tagLiteral, ""))
+
+ if tagLiteral == "" {
+ return ""
+ }
+
+ return "`" + tagLiteral + "`"
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/astutil/file-parser.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/astutil/file-parser.go
new file mode 100644
index 00000000..dc437fb2
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/astutil/file-parser.go
@@ -0,0 +1,213 @@
+// Package astutil provides AST file parsing utilities for the analyzer.
+package astutil
+
+import (
+ "go/ast"
+ "go/build"
+ "go/parser"
+ "go/token"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+ "sync/atomic"
+
+ "dev.gaijin.team/go/golib/e"
+ "dev.gaijin.team/go/golib/fields"
+ "golang.org/x/tools/go/analysis"
+)
+
+type ParseCallback func(fset *token.FileSet, file *ast.File) []analysis.Diagnostic
+
+// FileParser orchestrates AST parsing by triggering registered callbacks.
+// Each file is processed only once.
+//
+// Safe for concurrent use.
+type FileParser struct {
+ mu sync.RWMutex `exhaustruct:"optional"`
+ parsed map[string]bool
+ callbacks []ParseCallback `exhaustruct:"optional"`
+ parseFlags parser.Mode `exhaustruct:"optional"`
+ hits atomic.Uint64 `exhaustruct:"optional"`
+ misses atomic.Uint64 `exhaustruct:"optional"`
+}
+
+type Option func(*FileParser)
+
+// WithParseFlags sets parser flags for file parsing.
+// Default: parser.ParseComments | parser.SkipObjectResolution.
+func WithParseFlags(flags parser.Mode) Option {
+ return func(p *FileParser) { p.parseFlags = flags }
+}
+
+const parsedCachePrealloc = 64
+
+func NewFileParser(opts ...Option) *FileParser {
+ p := &FileParser{
+ parsed: make(map[string]bool, parsedCachePrealloc),
+ parseFlags: parser.ParseComments | parser.SkipObjectResolution,
+ }
+
+ for _, opt := range opts {
+ opt(p)
+ }
+
+ return p
+}
+
+func (p *FileParser) OnFileParsed(cb ParseCallback) {
+ p.callbacks = append(p.callbacks, cb)
+}
+
+// ProcessFiles triggers all callbacks for each provided AST file.
+// Already-parsed files are skipped.
+func (p *FileParser) ProcessFiles(fset *token.FileSet, files ...*ast.File) []analysis.Diagnostic {
+ var allDiags []analysis.Diagnostic
+
+ for _, file := range files {
+ filename := fset.Position(file.Pos()).Filename
+
+ p.mu.RLock()
+
+ alreadyParsed := p.parsed[filename]
+ p.mu.RUnlock()
+
+ if alreadyParsed {
+ p.hits.Add(1)
+
+ continue
+ }
+
+ p.mu.Lock()
+
+ if p.parsed[filename] {
+ p.mu.Unlock()
+ p.hits.Add(1)
+
+ continue
+ }
+
+ p.misses.Add(1)
+
+ for _, cb := range p.callbacks {
+ allDiags = append(allDiags, cb(fset, file)...)
+ }
+
+ p.parsed[filename] = true
+ p.mu.Unlock()
+ }
+
+ return allDiags
+}
+
+// ProcessFilename parses a file from disk and triggers all callbacks.
+// Returns nil if already processed or if the file belongs to the Go
+// distribution.
+func (p *FileParser) ProcessFilename(fset *token.FileSet, filename string) []analysis.Diagnostic {
+ if isGoRootFile(filename) {
+ return nil
+ }
+
+ p.mu.RLock()
+
+ alreadyParsed := p.parsed[filename]
+ p.mu.RUnlock()
+
+ if alreadyParsed {
+ p.hits.Add(1)
+
+ return nil
+ }
+
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ if p.parsed[filename] {
+ p.hits.Add(1)
+
+ return nil
+ }
+
+ p.misses.Add(1)
+
+ file, err := p.parse(fset, filename)
+ if err != nil {
+ p.parsed[filename] = true
+
+ return []analysis.Diagnostic{{
+ Pos: token.NoPos,
+ Message: err.Error(),
+ }}
+ }
+
+ var allDiags []analysis.Diagnostic
+
+ for _, cb := range p.callbacks {
+ allDiags = append(allDiags, cb(fset, file)...)
+ }
+
+ p.parsed[filename] = true
+
+ return allDiags
+}
+
+func (p *FileParser) Stats() (hits, misses, size uint64) {
+ p.mu.RLock()
+
+ size = uint64(len(p.parsed))
+
+ p.mu.RUnlock()
+
+ return p.hits.Load(), p.misses.Load(), size
+}
+
+// goRootPlaceholder is the literal prefix the compiler records instead of the
+// real GOROOT for files of the Go distribution, see cmd/internal/objabi.AbsFile.
+// Positions loaded from export data carry it as-is, so such paths can never be
+// opened.
+const goRootPlaceholder = "$GOROOT"
+
+// isGoRootFile reports whether filename belongs to the Go distribution. Its
+// sources carry no exhaustruct directives, so parsing them yields nothing and
+// their definitions are treated as directive-free.
+func isGoRootFile(filename string) bool {
+ return hasPathPrefix(filename, goRootPlaceholder) ||
+ hasPathPrefix(filename, build.Default.GOROOT)
+}
+
+// hasPathPrefix reports whether path starts with prefix at a path element
+// boundary. Separators are normalized, since the compiler records slashes on
+// every platform while GOROOT uses the native separator. An empty prefix, as
+// an unset or root GOROOT normalizes to, matches nothing rather than
+// everything.
+func hasPathPrefix(path, prefix string) bool {
+ prefix = strings.TrimSuffix(filepath.ToSlash(prefix), "/")
+ if prefix == "" {
+ return false
+ }
+
+ path = filepath.ToSlash(path)
+
+ if !strings.HasPrefix(path, prefix) {
+ return false
+ }
+
+ rest := path[len(prefix):]
+
+ return rest == "" || rest[0] == '/'
+}
+
+func (p *FileParser) parse(fset *token.FileSet, filename string) (*ast.File, error) {
+ //nolint:gosec // filename is derived from source code, not user input
+ content, err := os.ReadFile(filename)
+ if err != nil {
+ return nil, e.NewFrom("read file", err, fields.F("filename", filename))
+ }
+
+ file, err := parser.ParseFile(fset, filename, content, p.parseFlags)
+ if err != nil {
+ return nil, e.NewFrom("parse file", err, fields.F("filename", filename))
+ }
+
+ return file, nil
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/cache/cache.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/cache/cache.go
new file mode 100644
index 00000000..c480c6b3
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/cache/cache.go
@@ -0,0 +1,100 @@
+// Package cache provides a generic thread-safe cache with hit/miss tracking.
+package cache
+
+import (
+ "sync"
+ "sync/atomic"
+)
+
+type Cache[K comparable, V any] struct {
+ entries map[K]V
+ mu sync.RWMutex `exhaustruct:"optional"`
+ hits atomic.Uint64 `exhaustruct:"optional"`
+ misses atomic.Uint64 `exhaustruct:"optional"`
+}
+
+func New[K comparable, V any](initialCapacity int) *Cache[K, V] {
+ return &Cache[K, V]{
+ entries: make(map[K]V, initialCapacity),
+ }
+}
+
+func (c *Cache[K, V]) Get(key K) (v V, ok bool) {
+ c.mu.RLock()
+
+ v, ok = c.entries[key]
+
+ c.mu.RUnlock()
+
+ if ok {
+ c.hits.Add(1)
+ }
+
+ return v, ok
+}
+
+// Peek returns the value without updating hit/miss counters. Use it when the
+// caller has already recorded the miss that triggered the fill and a follow-up
+// read for the just-written entry must not inflate the hit rate.
+func (c *Cache[K, V]) Peek(key K) (v V, ok bool) {
+ c.mu.RLock()
+
+ v, ok = c.entries[key]
+
+ c.mu.RUnlock()
+
+ return v, ok
+}
+
+// Set stores value and increments miss counter (caller computed the value).
+func (c *Cache[K, V]) Set(key K, value V) {
+ c.mu.Lock()
+
+ c.entries[key] = value
+ c.misses.Add(1)
+
+ c.mu.Unlock()
+}
+
+// GetOrSet uses double-check locking to avoid computing values that are
+// cached between the initial read check and acquiring the write lock.
+func (c *Cache[K, V]) GetOrSet(key K, compute func() V) V {
+ c.mu.RLock()
+
+ if v, ok := c.entries[key]; ok {
+ c.mu.RUnlock()
+ c.hits.Add(1)
+
+ return v
+ }
+
+ c.mu.RUnlock()
+
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ // Double-check after acquiring write lock.
+ if v, ok := c.entries[key]; ok {
+ c.hits.Add(1)
+
+ return v
+ }
+
+ c.misses.Add(1)
+
+ v := compute()
+
+ c.entries[key] = v
+
+ return v
+}
+
+func (c *Cache[K, V]) Stats() (hits, misses, size uint64) {
+ c.mu.RLock()
+
+ size = uint64(len(c.entries))
+
+ c.mu.RUnlock()
+
+ return c.hits.Load(), c.misses.Load(), size
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/directive/directive.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/directive/directive.go
new file mode 100644
index 00000000..aa7f8d90
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/directive/directive.go
@@ -0,0 +1,95 @@
+package directive
+
+import (
+ "slices"
+ "strings"
+
+ "dev.gaijin.team/go/golib/e"
+)
+
+var (
+ ErrEmptyDirective = e.New("empty directive")
+ ErrUnknownDirective = e.New("unknown directive")
+ ErrDuplicateDirectives = e.New("duplicate directives")
+)
+
+type Directive string
+
+const (
+ // Ignore skips checking for a specific struct literal.
+ Ignore Directive = "ignore"
+ // Enforce forces check even if type is excluded.
+ Enforce Directive = "enforce"
+ // Optional marks a field as optional.
+ Optional Directive = "optional"
+)
+
+func (d Directive) IsValid() bool {
+ switch d {
+ case Ignore, Enforce, Optional:
+ return true
+
+ default:
+ return false
+ }
+}
+
+// Directives represents a collection of directives for a single line.
+// Multiple directives can be specified comma-separated: //exhaustruct:enforce,optional.
+type Directives []Directive
+
+func (ds Directives) Contains(d Directive) bool {
+ return slices.Contains(ds, d)
+}
+
+// directivePrefix is the exact prefix for exhaustruct directives.
+// Format: //exhaustruct: [optional comment].
+const directivePrefix = "//exhaustruct:"
+
+func Parse(text string) (found bool, result Directives, errs []error) {
+ text, found = strings.CutPrefix(text, directivePrefix)
+ if !found {
+ return false, nil, nil
+ }
+
+ if idx := strings.IndexAny(text, " \t\n"); idx > 0 {
+ text = text[:idx]
+ }
+
+ if text == "" {
+ return true, nil, []error{ErrEmptyDirective}
+ }
+
+ parts := strings.Split(text, ",")
+
+ result = make(Directives, 0, len(parts))
+
+ var hasDups bool
+
+ for _, part := range parts {
+ d := Directive(part)
+
+ if !d.IsValid() {
+ errs = append(errs, ErrUnknownDirective.WithField("directive", d))
+ continue
+ }
+
+ // giving the resulting size, linear search would be most efficient
+ if slices.Contains(result, d) {
+ hasDups = true
+ continue
+ }
+
+ result = append(result, d)
+ }
+
+ if hasDups {
+ errs = append(errs, ErrDuplicateDirectives)
+ }
+
+ if len(result) == 0 {
+ result = nil
+ }
+
+ return true, result, errs
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/directive/scanner.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/directive/scanner.go
new file mode 100644
index 00000000..0de61ad5
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/directive/scanner.go
@@ -0,0 +1,189 @@
+package directive
+
+import (
+ "go/ast"
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+
+ "dev.gaijin.team/go/exhaustruct/v5/internal/astutil"
+ "dev.gaijin.team/go/exhaustruct/v5/internal/cache"
+)
+
+// Scanner provides thread-safe caching and lookup of file directives.
+type Scanner struct {
+ parser *astutil.FileParser
+ cache *cache.Cache[string, fileDirectives]
+}
+
+const cachePreallocSize = 64
+
+// NewScanner creates a new directive scanner that registers a callback
+// with the file parser to extract directives from parsed files.
+func NewScanner(parser *astutil.FileParser) *Scanner {
+ s := &Scanner{
+ parser: parser,
+ cache: cache.New[string, fileDirectives](cachePreallocSize),
+ }
+
+ parser.OnFileParsed(s.onFileParsed)
+
+ return s
+}
+
+func (s *Scanner) onFileParsed(fset *token.FileSet, file *ast.File) []analysis.Diagnostic {
+ filename := fset.Position(file.Pos()).Filename
+
+ fd, diags := s.parseFileDirectives(fset, file)
+
+ s.cache.Set(filename, fd)
+
+ return diags
+}
+
+// ProcessFiles pre-populates the cache by delegating to FileParser.ProcessFiles.
+// Returns diagnostics from directive parsing.
+func (s *Scanner) ProcessFiles(fset *token.FileSet, files ...*ast.File) []analysis.Diagnostic {
+ return s.parser.ProcessFiles(fset, files...)
+}
+
+// Lookup returns the directives at the given source position.
+// If the file is not in cache, triggers FileParser.ProcessFilename to parse it.
+func (s *Scanner) Lookup(fset *token.FileSet, pos token.Position) (Directives, []analysis.Diagnostic) {
+ if pos.Filename == "" {
+ return nil, nil
+ }
+
+ if fd, ok := s.cache.Get(pos.Filename); ok {
+ return fd[pos.Line], nil
+ }
+
+ // Cache miss - parse file (triggers onFileParsed callback, which stores
+ // the result via cache.Set and increments the miss counter).
+ diags := s.parser.ProcessFilename(fset, pos.Filename)
+
+ // Peek avoids counting this self-induced read as a hit — the miss was
+ // already recorded by Set above.
+ if fd, ok := s.cache.Peek(pos.Filename); ok {
+ return fd[pos.Line], diags
+ }
+
+ // Still not in cache means parsing failed.
+ return nil, diags
+}
+
+func (s *Scanner) Stats() (hits, misses, size uint64) {
+ return s.cache.Stats()
+}
+
+// fileDirectives holds directives found in a single file, indexed by line number.
+type fileDirectives map[int]Directives
+
+// parseFileDirectives parses an AST file and extracts all exhaustruct directives.
+// Returns diagnostics in case file parsing errors, directive parsing errors, or
+// conflicting directives for the same target line.
+func (*Scanner) parseFileDirectives(fset *token.FileSet, file *ast.File) (fileDirectives, []analysis.Diagnostic) {
+ directives, diagnostics := parseCommentDirectives(fset, file.Comments)
+
+ if len(directives) == 0 {
+ return nil, diagnostics
+ }
+
+ ast.Inspect(file, func(n ast.Node) bool {
+ switch n.(type) {
+ case nil, *ast.Comment, *ast.CommentGroup:
+ return false
+ }
+
+ line := fset.Position(n.Pos()).Line
+ if d, ok := directives[line]; ok {
+ d.targetLine = line
+ directives[line] = d
+ }
+
+ return true
+ })
+
+ result := make(fileDirectives, len(directives))
+
+ for line, d := range directives {
+ _, exists := result[d.targetLine]
+ if !exists {
+ result[d.targetLine] = d.directives
+ continue
+ }
+
+ pos := d.pos
+
+ // directives from block comments win over inline comments
+ if line != d.targetLine {
+ result[d.targetLine] = d.directives
+ pos = directives[d.targetLine].pos
+ }
+
+ diagnostics = append(diagnostics, analysis.Diagnostic{
+ Pos: pos,
+ Message: "directive ignored, conflicting directive already exists for the same target line",
+ })
+ }
+
+ return result, diagnostics
+}
+
+type parsedDirective struct {
+ pos token.Pos
+ targetLine int
+ directives Directives
+}
+
+func parseCommentDirectives(
+ fset *token.FileSet,
+ comments []*ast.CommentGroup,
+) (map[int]parsedDirective, []analysis.Diagnostic) {
+ var (
+ directives = make(map[int]parsedDirective)
+ diagnostics []analysis.Diagnostic
+ )
+
+ for _, cg := range comments {
+ hasDirective := false
+
+ for _, comment := range cg.List {
+ found, parsed, errs := Parse(comment.Text)
+ if !found {
+ continue
+ }
+
+ pos := comment.Pos()
+
+ for _, err := range errs {
+ diagnostics = append(diagnostics, analysis.Diagnostic{
+ Pos: pos,
+ Message: err.Error(),
+ })
+ }
+
+ if len(parsed) == 0 {
+ continue
+ }
+
+ if hasDirective {
+ diagnostics = append(diagnostics, analysis.Diagnostic{
+ Pos: pos,
+ Message: "multiple exhaustruct directives in a single comment group, ignoring",
+ })
+
+ continue
+ }
+
+ hasDirective = true
+ directives[fset.Position(pos).Line] = parsedDirective{
+ pos: pos,
+ targetLine: fset.Position(cg.End()).Line + 1,
+ directives: parsed,
+ }
+ }
+ }
+
+ return directives, diagnostics
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/pattern/list.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/pattern/list.go
new file mode 100644
index 00000000..c715839f
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/pattern/list.go
@@ -0,0 +1,63 @@
+package pattern
+
+import (
+ "regexp"
+
+ "dev.gaijin.team/go/golib/e"
+ "dev.gaijin.team/go/golib/fields"
+)
+
+// List is a collection of compiled regular expressions.
+type List []*regexp.Regexp
+
+// NewList compiles patterns into a List.
+// Returns error if any pattern is empty or invalid.
+func NewList(patterns ...string) (List, error) {
+ if len(patterns) == 0 {
+ return nil, nil
+ }
+
+ list := make(List, 0, len(patterns))
+
+ for _, pattern := range patterns {
+ re, err := compilePattern(pattern)
+ if err != nil {
+ return nil, err
+ }
+
+ list = append(list, re)
+ }
+
+ return list, nil
+}
+
+// MatchFullString returns true if any regex matches the entire string.
+// Pattern "test" matches "test" but not "testing" or "contest".
+func (l List) MatchFullString(target string) bool {
+ if len(l) == 0 {
+ return false
+ }
+
+ for i := range len(l) {
+ // A match spanning [0, len(target)) covers every byte of target, so the
+ // matched substring is target itself — no need to allocate it for comparison.
+ if loc := l[i].FindStringIndex(target); loc != nil && loc[0] == 0 && loc[1] == len(target) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func compilePattern(pattern string) (*regexp.Regexp, error) {
+ if pattern == "" {
+ return nil, e.New("empty regular expression is not allowed")
+ }
+
+ re, err := regexp.Compile(pattern)
+ if err != nil {
+ return nil, e.NewFrom("compile regular expression", err, fields.F("pattern", pattern))
+ }
+
+ return re, nil
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/structure/origin-scanner.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/structure/origin-scanner.go
new file mode 100644
index 00000000..4f8c774d
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/structure/origin-scanner.go
@@ -0,0 +1,121 @@
+package structure
+
+import (
+ "go/ast"
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+
+ "dev.gaijin.team/go/exhaustruct/v5/internal/astutil"
+ "dev.gaijin.team/go/exhaustruct/v5/internal/cache"
+)
+
+type TypeOrigin uint8
+
+const (
+ OriginUnknown TypeOrigin = iota
+ OriginStruct
+ OriginAlias
+ OriginDerived
+)
+
+type fileOrigins map[string]TypeOrigin
+
+// OriginScanner extracts type origin information from AST files.
+// Registers with FileParser to process files as they are parsed.
+// Thread-safe.
+type OriginScanner struct {
+ parser *astutil.FileParser
+ cache *cache.Cache[string, fileOrigins]
+}
+
+const originCachePrealloc = 64
+
+func NewOriginScanner(parser *astutil.FileParser) *OriginScanner {
+ o := &OriginScanner{
+ parser: parser,
+ cache: cache.New[string, fileOrigins](originCachePrealloc),
+ }
+
+ parser.OnFileParsed(o.onFileParsed)
+
+ return o
+}
+
+func (o *OriginScanner) onFileParsed(
+ fset *token.FileSet,
+ file *ast.File,
+) []analysis.Diagnostic {
+ filename := fset.Position(file.Pos()).Filename
+
+ origins := extractTypeOrigins(file)
+
+ o.cache.Set(filename, origins)
+
+ return nil
+}
+
+// Lookup returns the type origin for a named type in the given file.
+// Triggers on-demand parsing if file is not cached.
+func (o *OriginScanner) Lookup(
+ fset *token.FileSet,
+ filename string,
+ typeName string,
+) TypeOrigin {
+ if filename == "" || typeName == "" {
+ return OriginUnknown
+ }
+
+ if origins, ok := o.cache.Get(filename); ok {
+ return origins[typeName]
+ }
+
+ // Cache miss - parse file (onFileParsed stores the result via cache.Set
+ // and records the miss). Peek avoids inflating the hit rate by re-reading
+ // the entry we just wrote.
+ o.parser.ProcessFilename(fset, filename)
+
+ if origins, ok := o.cache.Peek(filename); ok {
+ return origins[typeName]
+ }
+
+ return OriginUnknown
+}
+
+func (o *OriginScanner) Stats() (hits, misses, size uint64) {
+ return o.cache.Stats()
+}
+
+func extractTypeOrigins(file *ast.File) fileOrigins {
+ origins := make(fileOrigins)
+
+ for _, decl := range file.Decls {
+ gd, ok := decl.(*ast.GenDecl)
+ if !ok || gd.Tok != token.TYPE {
+ continue
+ }
+
+ for _, spec := range gd.Specs {
+ ts, ok := spec.(*ast.TypeSpec)
+ if !ok {
+ continue
+ }
+
+ origins[ts.Name.Name] = classifyTypeSpec(ts)
+ }
+ }
+
+ return origins
+}
+
+func classifyTypeSpec(ts *ast.TypeSpec) TypeOrigin {
+ if ts.Assign != token.NoPos {
+ return OriginAlias
+ }
+
+ if _, isStruct := ts.Type.(*ast.StructType); isStruct {
+ return OriginStruct
+ }
+
+ return OriginDerived
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/structure/processor.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/structure/processor.go
new file mode 100644
index 00000000..1c63030e
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/structure/processor.go
@@ -0,0 +1,254 @@
+package structure
+
+import (
+ "go/token"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+
+ "dev.gaijin.team/go/exhaustruct/v5/internal/cache"
+ "dev.gaijin.team/go/exhaustruct/v5/internal/directive"
+ "dev.gaijin.team/go/exhaustruct/v5/internal/pattern"
+)
+
+type Processor struct {
+ directives *directive.Scanner
+ origins *OriginScanner
+ fieldsCache *cache.Cache[*types.Struct, structFields]
+ structCache *cache.Cache[token.Position, *Struct]
+
+ enforce pattern.List `exhaustruct:"optional"`
+ ignore pattern.List `exhaustruct:"optional"`
+ optional pattern.List `exhaustruct:"optional"`
+ allowEmpty pattern.List `exhaustruct:"optional"`
+}
+
+type Option func(*Processor)
+
+func WithEnforce(patterns pattern.List) Option {
+ return func(p *Processor) { p.enforce = patterns }
+}
+
+func WithIgnore(patterns pattern.List) Option {
+ return func(p *Processor) { p.ignore = patterns }
+}
+
+func WithOptional(patterns pattern.List) Option {
+ return func(p *Processor) { p.optional = patterns }
+}
+
+func WithAllowEmpty(patterns pattern.List) Option {
+ return func(p *Processor) { p.allowEmpty = patterns }
+}
+
+const cachePreallocSize = 64
+
+func NewProcessor(directives *directive.Scanner, origins *OriginScanner, opts ...Option) *Processor {
+ p := &Processor{
+ directives: directives,
+ origins: origins,
+ fieldsCache: cache.New[*types.Struct, structFields](cachePreallocSize),
+ structCache: cache.New[token.Position, *Struct](cachePreallocSize),
+ }
+
+ for _, opt := range opts {
+ opt(p)
+ }
+
+ return p
+}
+
+// Directives returns the directive scanner the processor was constructed
+// with, shared so callers can resolve use-site directives against the same
+// cache.
+func (p *Processor) Directives() *directive.Scanner {
+ return p.directives
+}
+
+// ResolveStruct returns Struct metadata for the given type.
+// Type resolution (pointers, aliases) is done by the caller.
+//
+// Parameters:
+// - typeName: the type's TypeName, or nil for anonymous structs
+// - strct: the underlying struct type (required)
+// - pos: position of type definition (from analyzer's AST inspection)
+// - callerPkg: package context, used for anonymous struct path
+func (p *Processor) ResolveStruct(
+ fset *token.FileSet,
+ typeName *types.TypeName,
+ strct *types.Struct,
+ pos token.Pos,
+ callerPkg *types.Package,
+) (*Struct, []analysis.Diagnostic) {
+ if strct == nil {
+ return nil, nil
+ }
+
+ position := fset.Position(pos)
+
+ // Check cache before allocating
+ if position.IsValid() {
+ if cached, ok := p.structCache.Get(position); ok {
+ return cached, nil
+ }
+ }
+
+ s := p.buildStruct(typeName, position, callerPkg)
+
+ diags := p.populateFields(fset, s, strct)
+ p.resolveStructOrigin(fset, s)
+
+ diags = append(diags, p.resolveStructDirectives(fset, s)...)
+ p.matchStructPatterns(s)
+
+ if s.Position.IsValid() {
+ p.structCache.Set(s.Position, s)
+ }
+
+ return s, diags
+}
+
+// buildStruct creates Struct metadata from type info.
+func (*Processor) buildStruct(typeName *types.TypeName, pos token.Position, callerPkg *types.Package) *Struct {
+ if typeName != nil {
+ pkg := typeName.Pkg()
+
+ return &Struct{
+ Name: typeName.Name(),
+ FullPath: pkg.Path() + "." + typeName.Name(),
+ PackageName: pkg.Name(),
+ Position: pos,
+ }
+ }
+
+ // Anonymous struct
+ return &Struct{
+ Name: AnonymousName,
+ FullPath: callerPkg.Path() + "." + AnonymousName,
+ PackageName: callerPkg.Name(),
+ Position: pos,
+ }
+}
+
+func (p *Processor) getStructFields(fset *token.FileSet, strct *types.Struct) (structFields, []analysis.Diagnostic) {
+ if fields, ok := p.fieldsCache.Get(strct); ok {
+ return fields, nil
+ }
+
+ fields, diags := p.resolveStructFields(fset, strct)
+
+ p.fieldsCache.Set(strct, fields)
+
+ return fields, diags
+}
+
+func (p *Processor) resolveStructFields(
+ fset *token.FileSet,
+ strct *types.Struct,
+) (structFields, []analysis.Diagnostic) {
+ result := structFields{
+ packagePath: "",
+ fields: make([]fieldInfo, 0, strct.NumFields()),
+ }
+
+ var diags []analysis.Diagnostic
+
+ for f := range strct.Fields() {
+ if result.packagePath == "" && f.Pkg() != nil {
+ result.packagePath = f.Pkg().Path()
+ }
+
+ field := fieldInfo{
+ name: f.Name(),
+ exported: f.Exported(),
+ }
+
+ if p.directives != nil {
+ fieldPos := fset.Position(f.Pos())
+ dirs, d := p.directives.Lookup(fset, fieldPos)
+
+ diags = append(diags, d...)
+
+ field.enforced = dirs.Contains(directive.Enforce)
+ field.optional = dirs.Contains(directive.Optional)
+ }
+
+ result.fields = append(result.fields, field)
+ }
+
+ return result, diags
+}
+
+func (p *Processor) populateFields(fset *token.FileSet, s *Struct, strct *types.Struct) []analysis.Diagnostic {
+ resolved, diags := p.getStructFields(fset, strct)
+
+ // Fields are external when declared in a different package than the struct type.
+ // This happens for derived types and aliases from external packages.
+ //
+ // Rationale behind that filtering is that noone except package that has declared
+ // the struct can access unexported fields, therefore we can simply filter them
+ // out to save up on storage. Usage of derived type from the package of structure
+ // definition is simply impossible since it will cause import cycle - thus, such
+ // filtering is safe.
+ fieldsExternal := resolved.packagePath != s.PackagePath()
+
+ s.Fields = Fields{
+ PackagePath: resolved.packagePath,
+ Items: make([]Field, 0, len(resolved.fields)),
+ }
+
+ for _, sf := range resolved.fields {
+ if fieldsExternal && !sf.exported {
+ continue
+ }
+
+ fieldPath := s.FullPath + "#" + sf.name
+
+ s.Fields.Items = append(s.Fields.Items, Field{
+ Name: sf.name,
+ Exported: sf.exported,
+ Enforced: sf.enforced,
+ Optional: sf.optional,
+ PatternEnforced: p.enforce.MatchFullString(fieldPath),
+ PatternOptional: p.optional.MatchFullString(fieldPath),
+ })
+ }
+
+ return diags
+}
+
+func (p *Processor) resolveStructOrigin(fset *token.FileSet, s *Struct) {
+ if !s.Position.IsValid() || s.Name == AnonymousName {
+ return
+ }
+
+ origin := p.origins.Lookup(fset, s.Position.Filename, s.Name)
+
+ s.IsAlias = origin == OriginAlias
+ s.IsDerived = origin == OriginDerived
+}
+
+func (p *Processor) resolveStructDirectives(fset *token.FileSet, s *Struct) []analysis.Diagnostic {
+ if p.directives == nil || !s.Position.IsValid() {
+ return nil
+ }
+
+ dirs, diags := p.directives.Lookup(fset, s.Position)
+
+ s.Enforced = dirs.Contains(directive.Enforce)
+ s.Ignored = dirs.Contains(directive.Ignore)
+ s.Optional = dirs.Contains(directive.Optional)
+
+ return diags
+}
+
+func (p *Processor) matchStructPatterns(s *Struct) {
+ s.PatternEnforced = p.enforce.MatchFullString(s.FullPath)
+ s.PatternIgnored = p.ignore.MatchFullString(s.FullPath)
+ s.PatternOptional = p.optional.MatchFullString(s.FullPath)
+ s.AllowEmptyDecl = p.allowEmpty.MatchFullString(s.FullPath)
+}
+
+func (p *Processor) Stats() (hits, misses, size uint64) {
+ return p.structCache.Stats()
+}
diff --git a/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/structure/struct.go b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/structure/struct.go
new file mode 100644
index 00000000..c6cd49f2
--- /dev/null
+++ b/vendor/dev.gaijin.team/go/exhaustruct/v5/internal/structure/struct.go
@@ -0,0 +1,224 @@
+package structure
+
+import (
+ "go/ast"
+ "go/token"
+ "strings"
+)
+
+const AnonymousName = ""
+
+// fieldInfo contains raw field data independent of type name.
+type fieldInfo struct {
+ // name is the name of the field.
+ name string
+ // exported indicates if the field is exported.
+ exported bool `exhaustruct:"optional"`
+ // enforced indicates if the field is enforced via directive.
+ enforced bool `exhaustruct:"optional"`
+ // optional indicates if the field is optional via directive.
+ optional bool `exhaustruct:"optional"`
+}
+
+// structFields contains field information for a struct, independent of type name.
+type structFields struct {
+ // packagePath is the package path where fields are declared.
+ packagePath string
+ // fields is the list of fields in declaration order.
+ fields []fieldInfo
+}
+
+type Struct struct {
+ Name string
+ FullPath string
+ PackageName string
+
+ Position token.Position `exhaustruct:"optional"`
+ Fields Fields `exhaustruct:"optional"`
+
+ Enforced bool `exhaustruct:"optional"`
+ Ignored bool `exhaustruct:"optional"`
+ Optional bool `exhaustruct:"optional"`
+
+ PatternEnforced bool `exhaustruct:"optional"`
+ PatternIgnored bool `exhaustruct:"optional"`
+ PatternOptional bool `exhaustruct:"optional"`
+
+ AllowEmptyDecl bool `exhaustruct:"optional"`
+
+ // Detected via OriginScanner AST inspection before types.Unalias.
+ IsAlias bool `exhaustruct:"optional"`
+ IsDerived bool `exhaustruct:"optional"`
+}
+
+// PackagePath returns the package path of the struct type.
+func (s *Struct) PackagePath() string {
+ if idx := strings.LastIndex(s.FullPath, "."); idx >= 0 {
+ return s.FullPath[:idx]
+ }
+
+ return s.FullPath
+}
+
+// IsEnforced returns true if struct is enforced via directive or pattern.
+func (s *Struct) IsEnforced() bool {
+ return s.Enforced || s.PatternEnforced
+}
+
+// IsIgnored returns true if struct is ignored via directive or pattern.
+func (s *Struct) IsIgnored() bool {
+ return s.Ignored || s.PatternIgnored
+}
+
+// IsOptional returns true if struct is optional via directive or pattern.
+func (s *Struct) IsOptional() bool {
+ return s.Optional || s.PatternOptional
+}
+
+// SkippedFields returns missing required fields for a composite literal.
+// callerPkgPath is used to determine if unexported fields are accessible.
+// For positional literals: returns fields after the last provided element.
+// For named literals: returns fields not present in the literal.
+func (s *Struct) SkippedFields(lit *ast.CompositeLit, callerPkgPath string) []Field {
+ externalPkg := s.Fields.PackagePath != callerPkgPath
+
+ if isNamedLiteral(lit) {
+ return s.skippedNamed(lit, externalPkg)
+ }
+
+ return s.skippedPositional(len(lit.Elts), externalPkg)
+}
+
+// isNamedLiteral checks if a composite literal uses named fields. It treats
+// empty literals as not named, since positional literals checks are simpler.
+func isNamedLiteral(lit *ast.CompositeLit) bool {
+ if len(lit.Elts) == 0 {
+ return false
+ }
+
+ _, ok := lit.Elts[0].(*ast.KeyValueExpr)
+
+ return ok
+}
+
+func (s *Struct) skippedPositional(count int, externalPkg bool) []Field {
+ items := s.Fields.Items
+
+ if count >= len(items) {
+ return nil
+ }
+
+ remaining := items[count:]
+ missing := make([]Field, 0, len(remaining))
+
+ for _, f := range remaining {
+ if s.isFieldRequired(f, externalPkg) {
+ missing = append(missing, f)
+ }
+ }
+
+ if len(missing) == 0 {
+ return nil
+ }
+
+ return missing
+}
+
+func (s *Struct) skippedNamed(lit *ast.CompositeLit, externalPkg bool) []Field {
+ present := make(map[string]bool, len(lit.Elts))
+
+ for _, elt := range lit.Elts {
+ if kv, ok := elt.(*ast.KeyValueExpr); ok {
+ if k, ok := kv.Key.(*ast.Ident); ok {
+ present[k.Name] = true
+ }
+ }
+ }
+
+ missing := make([]Field, 0, len(s.Fields.Items)-len(present))
+
+ for _, f := range s.Fields.Items {
+ if !present[f.Name] && s.isFieldRequired(f, externalPkg) {
+ missing = append(missing, f)
+ }
+ }
+
+ if len(missing) == 0 {
+ return nil
+ }
+
+ return missing
+}
+
+func (s *Struct) isFieldRequired(f Field, externalPkg bool) bool {
+ // explicit field directives win over everything
+ if f.Enforced {
+ return true
+ }
+
+ if f.Optional {
+ return false
+ }
+
+ // field-level patterns apply only when they specifically target the field —
+ // i.e., the pattern matches the field path but not the struct path. A broad
+ // pattern that also matches the struct is handled via s.IsEnforced/IsOptional
+ // and must not silently promote unrelated fields to required/optional.
+ if f.PatternEnforced && !s.PatternEnforced {
+ return true
+ }
+
+ if f.PatternOptional && !s.PatternOptional {
+ return false
+ }
+
+ // optionality can be inherited from the structure settings
+ if s.IsOptional() {
+ return false
+ }
+
+ // unexported fields are only required for same-package usage
+ if externalPkg && !f.Exported {
+ return false
+ }
+
+ return true
+}
+
+type Field struct {
+ Name string
+ Exported bool `exhaustruct:"optional"`
+ Enforced bool `exhaustruct:"optional"`
+ Optional bool `exhaustruct:"optional"`
+
+ PatternEnforced bool `exhaustruct:"optional"`
+ PatternOptional bool `exhaustruct:"optional"`
+}
+
+// Fields is a collection of struct fields with shared package metadata.
+// Items are in declaration order (required for positional literals).
+type Fields struct {
+ PackagePath string
+ Items []Field
+}
+
+func FormatFieldNames(fields []Field) string {
+ switch len(fields) {
+ case 0:
+ return ""
+ case 1:
+ return fields[0].Name
+ }
+
+ var b strings.Builder
+
+ b.Grow(len(fields))
+ b.WriteString(fields[0].Name)
+
+ for _, s := range fields[1:] {
+ b.WriteString(", ")
+ b.WriteString(s.Name)
+ }
+
+ return b.String()
+}
diff --git a/vendor/dev.gaijin.team/go/golib/fields/field.go b/vendor/dev.gaijin.team/go/golib/fields/field.go
index 324b2970..716586ba 100644
--- a/vendor/dev.gaijin.team/go/golib/fields/field.go
+++ b/vendor/dev.gaijin.team/go/golib/fields/field.go
@@ -1,4 +1,3 @@
-// Package fields provides types and functions for working with key-value fields.
package fields
import (
diff --git a/vendor/dev.gaijin.team/go/golib/fields/list.go b/vendor/dev.gaijin.team/go/golib/fields/list.go
index 5a881f77..7da83b20 100644
--- a/vendor/dev.gaijin.team/go/golib/fields/list.go
+++ b/vendor/dev.gaijin.team/go/golib/fields/list.go
@@ -44,7 +44,7 @@ func (l List) ToDict() Dict {
// }
func (l List) All() iter.Seq2[string, any] {
return func(yield func(string, any) bool) {
- for i := 0; i < len(l); i++ {
+ for i := range len(l) {
if !yield(l[i].K, l[i].V) {
return
}
diff --git a/vendor/github.com/Abirdcfly/dupword/dupword.go b/vendor/github.com/Abirdcfly/dupword/dupword.go
index a3eaced8..5b482006 100644
--- a/vendor/github.com/Abirdcfly/dupword/dupword.go
+++ b/vendor/github.com/Abirdcfly/dupword/dupword.go
@@ -99,15 +99,17 @@ func NewAnalyzer() *analysis.Analyzer {
a.Flags.Var(&analyzer.keywords, "keyword", "keywords for detecting duplicate words")
a.Flags.Var(&analyzer.ignoreWords, "ignore", "ignore words")
a.Flags.BoolVar(&analyzer.commentsOnly, "comments-only", false, "check only comments, skip strings")
+ a.Flags.BoolVar(&analyzer.skipRawStrings, "skip-raw-strings", false, "skip raw string literals (backtick-delimited)")
a.Flags.Var(version{}, "V", "print version and exit")
return a
}
type analyzer struct {
- keywords keywords
- ignoreWords ignore
- commentsOnly bool
+ keywords keywords
+ ignoreWords ignore
+ commentsOnly bool
+ skipRawStrings bool
}
func (a *analyzer) run(pass *analysis.Pass) (interface{}, error) {
@@ -186,6 +188,9 @@ func (a *analyzer) fixDuplicateWordInString(pass *analysis.Pass, lit *ast.BasicL
if lit.Kind != token.STRING {
return
}
+ if a.skipRawStrings && len(lit.Value) > 0 && lit.Value[0] == '`' {
+ return
+ }
value, err := strconv.Unquote(lit.Value)
if err != nil {
fmt.Printf("lit.Value:%v, err: %v\n", lit.Value, err)
@@ -193,9 +198,14 @@ func (a *analyzer) fixDuplicateWordInString(pass *analysis.Pass, lit *ast.BasicL
value = lit.Value
}
quote := value != lit.Value
+ isRawString := quote && len(lit.Value) > 0 && lit.Value[0] == '`'
update, keyword, find := a.Check(value)
if quote {
- update = strconv.Quote(update)
+ if isRawString {
+ update = "`" + update + "`"
+ } else {
+ update = strconv.Quote(update)
+ }
}
if find {
pass.Report(analysis.Diagnostic{Pos: lit.Pos(), End: lit.End(), Message: fmt.Sprintf(Message, keyword), SuggestedFixes: []analysis.SuggestedFix{{
@@ -268,8 +278,8 @@ func (a *analyzer) checkOneKey(raw, key string) (new string, findWord string, fi
// space start position
spaceStart = i
curWord = raw[wordStart:i]
- } else if i == len(raw)-1 {
- // last position
+ } else if i == len(raw)-1 && !unicode.IsSpace(r) {
+ // last position (non-space): write the final word
word := raw[wordStart:]
if ((key != "" && word == key) || key == "") && word == preWord {
if !a.excludeWords(cutTrailingCommas(word)) {
@@ -283,6 +293,25 @@ func (a *analyzer) checkOneKey(raw, key string) (new string, findWord string, fi
}
lastRune = r
}
+ // Flush remaining content when the string ends with whitespace:
+ // the last word (curWord) and trailing whitespace haven't been written yet.
+ if len(raw) > 0 && unicode.IsSpace(rune(raw[len(raw)-1])) {
+ if curWord != "" {
+ if ((key != "" && curWord == key) || key == "") && curWord == preWord && curWord != "" {
+ if !a.excludeWords(cutTrailingCommas(curWord)) {
+ find = true
+ findWordMap[curWord] = true
+ } else {
+ newLine.WriteString(lastSpace)
+ newLine.WriteString(curWord)
+ }
+ } else {
+ newLine.WriteString(lastSpace)
+ newLine.WriteString(curWord)
+ }
+ }
+ newLine.WriteString(raw[spaceStart:])
+ }
if find {
new = newLine.String()
findWordSlice := make([]string, len(findWordMap))
diff --git a/vendor/github.com/AlwxSin/noinlineerr/noinlineerr.go b/vendor/github.com/AlwxSin/noinlineerr/noinlineerr.go
index 9bf56232..91d3c6bd 100644
--- a/vendor/github.com/AlwxSin/noinlineerr/noinlineerr.go
+++ b/vendor/github.com/AlwxSin/noinlineerr/noinlineerr.go
@@ -4,6 +4,7 @@ import (
"bytes"
"go/ast"
"go/printer"
+ "go/token"
"go/types"
"golang.org/x/tools/go/analysis"
@@ -11,7 +12,13 @@ import (
"golang.org/x/tools/go/ast/inspector"
)
-const errMessage = "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`"
+func errMessage(tok token.Token) string {
+ if tok == token.ASSIGN {
+ return "avoid inline error handling using `if err = ...; err != nil`; use plain assignment `err = ...`"
+ }
+
+ return "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`"
+}
func NewAnalyzer() *analysis.Analyzer {
return &analysis.Analyzer{
@@ -67,8 +74,8 @@ func inlineErrorInspector(pass *analysis.Pass) func(n ast.Node) {
// or there are any variables with same name
// then we can make a shadow conflict with other variables
// so don't do anything beside simple error message
- if len(assignStmt.Lhs) != 1 || shadowVarsExists(ident.Name, pass.TypesInfo.Scopes[ifStmt]) {
- pass.Reportf(ident.Pos(), errMessage)
+ if len(assignStmt.Lhs) != 1 || (assignStmt.Tok == token.DEFINE && shadowVarsExists(ident.Name, pass.TypesInfo.Scopes[ifStmt])) {
+ pass.Reportf(ident.Pos(), errMessage(assignStmt.Tok))
return
}
@@ -85,13 +92,13 @@ func inlineErrorInspector(pass *analysis.Pass) func(n ast.Node) {
pass.Report(analysis.Diagnostic{
Pos: ident.Pos(),
End: ident.End(),
- Message: errMessage,
+ Message: errMessage(assignStmt.Tok),
SuggestedFixes: []analysis.SuggestedFix{
{
Message: "move err assignment outside if",
TextEdits: []analysis.TextEdit{
{
- // insert err := ... before if
+ // insert err := ... or err = ... before if
Pos: ifStmt.Pos(),
End: ifStmt.Pos(),
NewText: []byte(assignText + "\n"),
diff --git a/vendor/github.com/ClickHouse/clickhouse-go-linter/LICENSE b/vendor/github.com/ClickHouse/clickhouse-go-linter/LICENSE
new file mode 100644
index 00000000..a7e77cb2
--- /dev/null
+++ b/vendor/github.com/ClickHouse/clickhouse-go-linter/LICENSE
@@ -0,0 +1,176 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/vendor/github.com/ClickHouse/clickhouse-go-linter/internal/util/util.go b/vendor/github.com/ClickHouse/clickhouse-go-linter/internal/util/util.go
new file mode 100644
index 00000000..68d13098
--- /dev/null
+++ b/vendor/github.com/ClickHouse/clickhouse-go-linter/internal/util/util.go
@@ -0,0 +1,33 @@
+package util
+
+import (
+ "go/ast"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+// IsChObj returns true if the input ast.Expr is of type clickhouse go driver
+func IsChObj(pass *analysis.Pass, expr ast.Expr, name string) bool {
+ t := pass.TypesInfo.TypeOf(expr)
+ if t == nil {
+ return false
+ }
+ named, ok := t.(*types.Named)
+ if !ok {
+ return false
+ }
+ obj := named.Obj()
+ if obj.Pkg() == nil {
+ return false
+ }
+ return obj.Pkg().Path() == "github.com/ClickHouse/clickhouse-go/v2/lib/driver" &&
+ obj.Name() == name
+}
+
+func IdentName(expr ast.Expr) string {
+ if id, ok := expr.(*ast.Ident); ok {
+ return id.Name
+ }
+ return ""
+}
diff --git a/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose/chbatchclose.go b/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose/chbatchclose.go
new file mode 100644
index 00000000..cc0f6894
--- /dev/null
+++ b/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose/chbatchclose.go
@@ -0,0 +1,227 @@
+package chbatchclose
+
+import (
+ "go/ast"
+ "go/token"
+ "os"
+ "strconv"
+
+ "github.com/ClickHouse/clickhouse-go-linter/internal/util"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+type analyzer struct {
+ // if true, report valid usages and log spurious but valid cases.
+ debug bool
+}
+
+func NewAnalyzer() *analysis.Analyzer {
+ debug, _ := strconv.ParseBool(os.Getenv("CH_GO_LINTER_DEBUG"))
+ a := analyzer{
+ debug: debug,
+ }
+ return &analysis.Analyzer{
+ Name: "chbatchclosecheck",
+ Doc: "chbatchclosecheck checks whether defer batch.Close() is called on ClickHouse driver Batch variables",
+ Run: a.run,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ }
+}
+
+func (a *analyzer) run(pass *analysis.Pass) (any, error) {
+ insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+
+ nodeFilter := []ast.Node{
+ (*ast.FuncDecl)(nil),
+ (*ast.FuncLit)(nil),
+ }
+
+ insp.Preorder(nodeFilter, func(n ast.Node) {
+ var body *ast.BlockStmt
+ switch fn := n.(type) {
+ case *ast.FuncDecl:
+ body = fn.Body
+ case *ast.FuncLit:
+ body = fn.Body
+ }
+
+ if body == nil {
+ return
+ }
+ a.checkFunc(pass, body)
+ })
+
+ return nil, nil
+}
+
+// batchUsage tracks whether a driver.Batch variable has a defer Close/Abort or is returned.
+type batchUsage struct {
+ assignPos token.Pos
+ deferredClose bool
+ returned bool
+}
+
+func (b *batchUsage) report(varName string, pass *analysis.Pass, debug bool) {
+ if b.assignPos == token.NoPos {
+ // no usage of Batch
+ return
+ }
+ if !b.deferredClose && !b.returned {
+ pass.Reportf(b.assignPos,
+ "clickhouse Batch %s must be closed defensively with defer %s.Close() after successful instantiation",
+ varName, varName)
+ } else if debug {
+ if b.deferredClose {
+ pass.Reportf(b.assignPos,
+ "clickhouse Batch %s is properly closed defensively after successful instantiation [valid]",
+ varName)
+ } else {
+ pass.Reportf(b.assignPos,
+ "clickhouse Batch %s is returned by the function [valid]",
+ varName)
+ }
+ }
+}
+
+// checkFunc analyzes a single function/closure body.
+// It does a single-pass collection of Batch assignments, defer Close/Abort calls, and return statements.
+// It does not descend into nested closures (they are handled as separate units by the Preorder visitor above).
+func (a *analyzer) checkFunc(pass *analysis.Pass, body *ast.BlockStmt) {
+ usages := map[string]*batchUsage{}
+
+ ast.Inspect(body, func(n ast.Node) bool {
+ if n == nil {
+ return false
+ }
+ // don't descend into nested closures
+ if n != body {
+ if _, ok := n.(*ast.FuncLit); ok {
+ return false
+ }
+ }
+
+ switch node := n.(type) {
+ case *ast.AssignStmt:
+ a.handleAssign(pass, node, usages)
+ case *ast.DeferStmt:
+ handleDefer(node, usages)
+ case *ast.ReturnStmt:
+ handleReturn(node, usages)
+ }
+
+ return true
+ })
+
+ // remaining usages that were not flushed
+ for varName, u := range usages {
+ u.report(varName, pass, a.debug)
+ }
+}
+
+// handleAssign checks if any LHS variable in the assignment is of type driver.Batch.
+// If a tracked variable is reassigned, it flushes/reports the previous tracking first.
+func (a *analyzer) handleAssign(pass *analysis.Pass, assign *ast.AssignStmt, usages map[string]*batchUsage) {
+ for _, lhs := range assign.Lhs {
+ name := util.IdentName(lhs)
+ if name == "" {
+ continue
+ }
+ if name == "_" && util.IsChObj(pass, lhs, "Batch") {
+ pass.Reportf(assign.Pos(), "clickhouse Batch assigned to blank identifier. Connection leak. clickhouse Batch must be instantiated and closed defensively with defer batch.Close() after successful instantiation")
+ continue
+ }
+
+ // if this var was already tracked, flush previous usage before re-tracking
+ if u, ok := usages[name]; ok {
+ u.report(name, pass, a.debug)
+ delete(usages, name)
+ }
+
+ if util.IsChObj(pass, lhs, "Batch") {
+ usages[name] = &batchUsage{assignPos: assign.Pos()}
+ }
+ }
+}
+
+// handleDefer checks if a defer statement calls Close() on a tracked Batch variable.
+// Two shapes are supported:
+// - direct selector call: defer batch.Close()
+// - immediately-invoked closure: defer func() { ... batch.Close() ... }()
+// (no params; nested FuncLits inside the closure body are not descended into)
+func handleDefer(deferStmt *ast.DeferStmt, usages map[string]*batchUsage) {
+ call := deferStmt.Call
+
+ switch fun := call.Fun.(type) {
+ case *ast.SelectorExpr:
+ varName := util.IdentName(fun.X)
+ if varName == "" {
+ return
+ }
+ u, exists := usages[varName]
+ if !exists {
+ return
+ }
+ if fun.Sel.Name == "Close" {
+ u.deferredClose = true
+ }
+ case *ast.FuncLit:
+ // only no-arg closures are supported for the moment
+ if fun.Type.Params != nil && len(fun.Type.Params.List) > 0 {
+ return
+ }
+ handleDeferredClosure(fun.Body, usages)
+ }
+}
+
+// handleDeferredClosure walks the body of a deferred closure looking for
+// `.Close()` calls. It does not descend into nested FuncLits, so
+// `defer func() { go func() { batch.Close() }() }()` and similar are not
+// treated as a valid defensive close.
+func handleDeferredClosure(body *ast.BlockStmt, usages map[string]*batchUsage) {
+ ast.Inspect(body, func(n ast.Node) bool {
+ if n == nil {
+ return false
+ }
+ // don't descend into nested closures (goroutines, callbacks, etc.)
+ if n != body {
+ if _, ok := n.(*ast.FuncLit); ok {
+ return false
+ }
+ }
+ call, ok := n.(*ast.CallExpr)
+ if !ok {
+ return true
+ }
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return true
+ }
+ if sel.Sel.Name != "Close" {
+ return true
+ }
+ varName := util.IdentName(sel.X)
+ if varName == "" {
+ return true
+ }
+ if u, exists := usages[varName]; exists {
+ u.deferredClose = true
+ }
+ return true
+ })
+}
+
+// handleReturn checks if any return value is a tracked Batch variable.
+func handleReturn(ret *ast.ReturnStmt, usages map[string]*batchUsage) {
+ for _, result := range ret.Results {
+ name := util.IdentName(result)
+ if name == "" {
+ continue
+ }
+ if u, exists := usages[name]; exists {
+ u.returned = true
+ }
+ }
+}
diff --git a/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr/chrowserr.go b/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr/chrowserr.go
new file mode 100644
index 00000000..bba0f82a
--- /dev/null
+++ b/vendor/github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr/chrowserr.go
@@ -0,0 +1,162 @@
+package chrowserr
+
+import (
+ "go/ast"
+ "go/token"
+ "log"
+ "os"
+ "strconv"
+
+ "github.com/ClickHouse/clickhouse-go-linter/internal/util"
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+type analyzer struct {
+ // if true, report valid usages and log spurious but valid cases.
+ debug bool
+}
+
+func NewAnalyzer() *analysis.Analyzer {
+ debug, _ := strconv.ParseBool(os.Getenv("CH_GO_LINTER_DEBUG"))
+ a := analyzer{
+ debug: debug,
+ }
+ return &analysis.Analyzer{
+ Name: "chrowserrcheck",
+ Doc: "chrowserrcheck checks whether ClickHouse driver Rows.Err is called after Rows.Next()",
+ Run: a.run,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ }
+}
+
+func (a *analyzer) run(pass *analysis.Pass) (any, error) {
+ insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+
+ nodeFilter := []ast.Node{
+ (*ast.FuncDecl)(nil),
+ (*ast.FuncLit)(nil),
+ }
+
+ insp.Preorder(nodeFilter, func(n ast.Node) {
+ var body *ast.BlockStmt
+ switch fn := n.(type) {
+ case *ast.FuncDecl:
+ body = fn.Body
+ case *ast.FuncLit:
+ body = fn.Body
+ }
+
+ if body == nil {
+ return
+ }
+ a.checkFunc(pass, body)
+ })
+
+ return nil, nil
+}
+
+// rowsUsage tracks Next/Err usage observations for a single Rows variable within a function.
+type rowsUsage struct {
+ nextPos token.Pos
+ errCalled bool
+}
+
+func (r *rowsUsage) report(varName string, pass *analysis.Pass, debug bool) {
+ if r.nextPos == token.NoPos {
+ // no usage of rows.Next()
+ return
+ }
+ // rows.Next() was called
+ if !r.errCalled {
+ pass.Reportf(r.nextPos,
+ "clickhouse %s.Err() must be checked after %s.Next()",
+ varName, varName)
+ } else if debug {
+ // for dev purpose - list valid usages
+ pass.Reportf(r.nextPos,
+ "clickhouse %s.Err() is properly called after %s.Next() [valid]",
+ varName, varName)
+ }
+}
+
+// checkFunc analyzes a single function/closure body.
+// It does a single-pass collection of Next() and Err() calls,
+// it does not descend into nested closures (they are handled as separate units by the Preorder visitor above).
+func (a *analyzer) checkFunc(pass *analysis.Pass, body *ast.BlockStmt) {
+ usages := map[string]*rowsUsage{}
+ ast.Inspect(body, func(n ast.Node) bool {
+ if n == nil {
+ return false
+ }
+ // don't descend into nested closures
+ if n != body {
+ if _, ok := n.(*ast.FuncLit); ok {
+ return false
+ }
+ }
+
+ // if a tracked var appears in an assignment, it means it is re-assigned - run lint report and flush var from usages.
+ if assign, ok := n.(*ast.AssignStmt); ok {
+ for _, lhs := range assign.Lhs {
+ name := util.IdentName(lhs)
+ if name == "" {
+ continue
+ }
+ if s, ok := usages[name]; ok {
+ s.report(name, pass, a.debug)
+ }
+ delete(usages, name)
+ }
+ // let ast.Inspect continue
+ return true
+ }
+
+ // handle CH driver method calls Next() and Err() - skip everything else
+ call, ok := n.(*ast.CallExpr)
+ if !ok {
+ return true
+ }
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return true
+ }
+ varName := util.IdentName(sel.X)
+ if varName == "" {
+ return true
+ }
+ if !util.IsChObj(pass, sel.X, "Rows") {
+ return true
+ }
+
+ // call is a CH driver Rows method call
+ switch sel.Sel.Name {
+ case "Next":
+ if _, exists := usages[varName]; !exists {
+ usages[varName] = &rowsUsage{nextPos: call.Pos()}
+ } else if a.debug {
+ log.Printf("Rows.Next() is written multiple times with no re-assignment. Valid but rare usage. If this observation is not correct, it is a bug in this linter library. Please reach out to maintainer.")
+ // in particular could be a bug in the re-assignment detection
+ }
+ case "Err":
+ if s, exists := usages[varName]; exists {
+ s.errCalled = true
+ s.report(varName, pass, a.debug)
+ delete(usages, varName)
+ } else if a.debug {
+ log.Printf("%s.Err() is called on ClickHouse Rows %s but %s.Next() was never called. Valid but unexpected usage. If this observation is not correct, it is a bug in this linter library. Please reach out to maintainer.",
+ varName, varName, varName)
+ // in particular could be a bug in the re-assignment detection
+ }
+
+ }
+
+ return true
+ })
+
+ // remaining usages that were not flushed (misusages only, as correct usages are flushed already)
+ for varName, s := range usages {
+ s.report(varName, pass, a.debug)
+ }
+}
diff --git a/vendor/github.com/Masterminds/semver/v3/.gitignore b/vendor/github.com/Masterminds/semver/v3/.gitignore
index 6b061e61..35f0e5a3 100644
--- a/vendor/github.com/Masterminds/semver/v3/.gitignore
+++ b/vendor/github.com/Masterminds/semver/v3/.gitignore
@@ -1 +1,2 @@
-_fuzz/
\ No newline at end of file
+_fuzz/
+.devcontainer/
\ No newline at end of file
diff --git a/vendor/github.com/Masterminds/semver/v3/.golangci.yml b/vendor/github.com/Masterminds/semver/v3/.golangci.yml
index fbc63325..24277f3a 100644
--- a/vendor/github.com/Masterminds/semver/v3/.golangci.yml
+++ b/vendor/github.com/Masterminds/semver/v3/.golangci.yml
@@ -1,27 +1,42 @@
-run:
- deadline: 2m
-
+version: "2"
linters:
- disable-all: true
+ default: none
enable:
- - misspell
- - govet
- - staticcheck
+ - dupl
- errcheck
- - unparam
+ - gocyclo
+ - gosec
+ - govet
- ineffassign
+ - misspell
- nakedret
- - gocyclo
- - dupl
- - goimports
- revive
- - gosec
- - gosimple
- - typecheck
+ - staticcheck
+ - unparam
- unused
-
-linters-settings:
- gofmt:
- simplify: true
- dupl:
- threshold: 600
+ settings:
+ dupl:
+ threshold: 600
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - goimports
+ settings:
+ gofmt:
+ simplify: true
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
diff --git a/vendor/github.com/Masterminds/semver/v3/constraints.go b/vendor/github.com/Masterminds/semver/v3/constraints.go
index 8b7a10f8..e8353bc4 100644
--- a/vendor/github.com/Masterminds/semver/v3/constraints.go
+++ b/vendor/github.com/Masterminds/semver/v3/constraints.go
@@ -21,21 +21,43 @@ type Constraints struct {
IncludePrerelease bool
}
+// MaxConstraintLen is the maximum allowed length of a constraint string.
+const MaxConstraintLen = 512
+
+// MaxConstraintGroups is the maximum number of OR groups allowed in a
+// constraint string.
+const MaxConstraintGroups = 32
+
+// ErrConstraintTooLong is returned when a constraint string exceeds the
+// maximum allowed length.
+var ErrConstraintTooLong = fmt.Errorf("constraint string is too long (max %d bytes)", MaxConstraintLen)
+
+// ErrTooManyConstraintGroups is returned when a constraint string contains
+// too many OR groups.
+var ErrTooManyConstraintGroups = fmt.Errorf("too many constraint groups (max %d)", MaxConstraintGroups)
+
// NewConstraint returns a Constraints instance that a Version instance can
// be checked against. If there is a parse error it will be returned.
func NewConstraint(c string) (*Constraints, error) {
+ if len(c) > MaxConstraintLen {
+ return nil, ErrConstraintTooLong
+ }
+
// Rewrite - ranges into a comparison operation.
c = rewriteRange(c)
ors := strings.Split(c, "||")
+ if len(ors) > MaxConstraintGroups {
+ return nil, ErrTooManyConstraintGroups
+ }
lenors := len(ors)
or := make([][]*constraint, lenors)
hasPre := make([]bool, lenors)
for k, v := range ors {
// Validate the segment
if !validConstraintRegex.MatchString(v) {
- return nil, fmt.Errorf("improper constraint: %s", v)
+ return nil, fmt.Errorf("improper constraint: %q", v)
}
cs := findConstraintRegex.FindAllString(v, -1)
@@ -104,9 +126,9 @@ func (cs Constraints) Validate(v *Version) (bool, []error) {
for _, c := range o {
// Before running the check handle the case there the version is
// a prerelease and the check is not searching for prereleases.
- if !(cs.IncludePrerelease || cs.containsPre[i]) && v.pre != "" {
+ if !cs.IncludePrerelease && !cs.containsPre[i] && v.pre != "" {
if !prerelesase {
- em := fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ em := fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
e = append(e, em)
prerelesase = true
}
@@ -258,7 +280,7 @@ func parseConstraint(c string) (*constraint, error) {
if len(c) > 0 {
m := constraintRegex.FindStringSubmatch(c)
if m == nil {
- return nil, fmt.Errorf("improper constraint: %s", c)
+ return nil, fmt.Errorf("improper constraint: %q", c)
}
cs := &constraint{
@@ -325,7 +347,7 @@ func constraintNotEqual(v *Version, c *constraint, includePre bool) (bool, error
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
if c.dirty {
@@ -335,7 +357,7 @@ func constraintNotEqual(v *Version, c *constraint, includePre bool) (bool, error
if c.con.Minor() != v.Minor() && !c.minorDirty {
return true, nil
} else if c.minorDirty {
- return false, fmt.Errorf("%s is equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is equal to %q", v, c.orig)
} else if c.con.Patch() != v.Patch() && !c.patchDirty {
return true, nil
} else if c.patchDirty {
@@ -345,15 +367,15 @@ func constraintNotEqual(v *Version, c *constraint, includePre bool) (bool, error
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is equal to %q", v, c.orig)
}
- return false, fmt.Errorf("%s is equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is equal to %q", v, c.orig)
}
}
eq := v.Equal(c.con)
if eq {
- return false, fmt.Errorf("%s is equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is equal to %q", v, c.orig)
}
return true, nil
@@ -364,7 +386,7 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
var eq bool
@@ -374,17 +396,17 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
}
if v.Major() > c.con.Major() {
return true, nil
} else if v.Major() < c.con.Major() {
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
} else if c.minorDirty {
// This is a range case such as >11. When the version is something like
// 11.1.0 is it not > 11. For that we would need 12 or higher
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
} else if c.patchDirty {
// This is for ranges such as >11.1. A version of 11.1.1 is not greater
// which one of 11.2.1 is greater
@@ -392,7 +414,7 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
}
// If we have gotten here we are not comparing pre-preleases and can use the
@@ -401,21 +423,21 @@ func constraintGreaterThan(v *Version, c *constraint, includePre bool) (bool, er
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than or equal to %q", v, c.orig)
}
func constraintLessThan(v *Version, c *constraint, includePre bool) (bool, error) {
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
eq := v.Compare(c.con) < 0
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is greater than or equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is greater than or equal to %q", v, c.orig)
}
func constraintGreaterThanEqual(v *Version, c *constraint, includePre bool) (bool, error) {
@@ -423,21 +445,21 @@ func constraintGreaterThanEqual(v *Version, c *constraint, includePre bool) (boo
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
eq := v.Compare(c.con) >= 0
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is less than %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than %q", v, c.orig)
}
func constraintLessThanEqual(v *Version, c *constraint, includePre bool) (bool, error) {
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
var eq bool
@@ -447,13 +469,13 @@ func constraintLessThanEqual(v *Version, c *constraint, includePre bool) (bool,
if eq {
return true, nil
}
- return false, fmt.Errorf("%s is greater than %s", v, c.orig)
+ return false, fmt.Errorf("%q is greater than %q", v, c.orig)
}
if v.Major() > c.con.Major() {
- return false, fmt.Errorf("%s is greater than %s", v, c.orig)
+ return false, fmt.Errorf("%q is greater than %q", v, c.orig)
} else if v.Major() == c.con.Major() && v.Minor() > c.con.Minor() && !c.minorDirty {
- return false, fmt.Errorf("%s is greater than %s", v, c.orig)
+ return false, fmt.Errorf("%q is greater than %q", v, c.orig)
}
return true, nil
@@ -469,11 +491,11 @@ func constraintTilde(v *Version, c *constraint, includePre bool) (bool, error) {
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
if v.LessThan(c.con) {
- return false, fmt.Errorf("%s is less than %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than %q", v, c.orig)
}
// ~0.0.0 is a special case where all constraints are accepted. It's
@@ -484,11 +506,11 @@ func constraintTilde(v *Version, c *constraint, includePre bool) (bool, error) {
}
if v.Major() != c.con.Major() {
- return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same major version as %q", v, c.orig)
}
if v.Minor() != c.con.Minor() && !c.minorDirty {
- return false, fmt.Errorf("%s does not have same major and minor version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same major and minor version as %q", v, c.orig)
}
return true, nil
@@ -500,7 +522,7 @@ func constraintTildeOrEqual(v *Version, c *constraint, includePre bool) (bool, e
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
if c.dirty {
@@ -512,7 +534,7 @@ func constraintTildeOrEqual(v *Version, c *constraint, includePre bool) (bool, e
return true, nil
}
- return false, fmt.Errorf("%s is not equal to %s", v, c.orig)
+ return false, fmt.Errorf("%q is not equal to %q", v, c.orig)
}
// ^* --> (any)
@@ -528,12 +550,12 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) {
// The existence of prereleases is checked at the group level and passed in.
// Exit early if the version has a prerelease but those are to be ignored.
if v.Prerelease() != "" && !includePre {
- return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
+ return false, fmt.Errorf("%q is a prerelease version and the constraint is only looking for release versions", v)
}
// This less than handles prereleases
if v.LessThan(c.con) {
- return false, fmt.Errorf("%s is less than %s", v, c.orig)
+ return false, fmt.Errorf("%q is less than %q", v, c.orig)
}
var eq bool
@@ -548,12 +570,12 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) {
if eq {
return true, nil
}
- return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same major version as %q", v, c.orig)
}
// ^ when the major is 0 and minor > 0 is >=0.y.z < 0.y+1
if c.con.Major() == 0 && v.Major() > 0 {
- return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same major version as %q", v, c.orig)
}
// If the con Minor is > 0 it is not dirty
if c.con.Minor() > 0 || c.patchDirty {
@@ -561,11 +583,11 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) {
if eq {
return true, nil
}
- return false, fmt.Errorf("%s does not have same minor version as %s. Expected minor versions to match when constraint major version is 0", v, c.orig)
+ return false, fmt.Errorf("%q does not have same minor version as %q. Expected minor versions to match when constraint major version is 0", v, c.orig)
}
// ^ when the minor is 0 and minor > 0 is =0.0.z
if c.con.Minor() == 0 && v.Minor() > 0 {
- return false, fmt.Errorf("%s does not have same minor version as %s", v, c.orig)
+ return false, fmt.Errorf("%q does not have same minor version as %q", v, c.orig)
}
// At this point the major is 0 and the minor is 0 and not dirty. The patch
@@ -574,7 +596,7 @@ func constraintCaret(v *Version, c *constraint, includePre bool) (bool, error) {
if eq {
return true, nil
}
- return false, fmt.Errorf("%s does not equal %s. Expect version and constraint to equal when major and minor versions are 0", v, c.orig)
+ return false, fmt.Errorf("%q does not equal %q. Expect version and constraint to equal when major and minor versions are 0", v, c.orig)
}
func isX(x string) bool {
diff --git a/vendor/github.com/Masterminds/semver/v3/version.go b/vendor/github.com/Masterminds/semver/v3/version.go
index 7a3ba738..da428760 100644
--- a/vendor/github.com/Masterminds/semver/v3/version.go
+++ b/vendor/github.com/Masterminds/semver/v3/version.go
@@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "math"
"regexp"
"strconv"
"strings"
@@ -48,8 +49,16 @@ var (
// ErrInvalidPrerelease is returned when the pre-release is an invalid format
ErrInvalidPrerelease = errors.New("invalid prerelease string")
+
+ // ErrVersionTooLong is returned when a version string exceeds the
+ // maximum allowed length.
+ ErrVersionTooLong = fmt.Errorf("version string is too long (max %d bytes)", MaxVersionLen)
)
+// MaxVersionLen is the maximum allowed length of a version string. This guards
+// against unbounded input causing excessive memory allocations during parsing.
+const MaxVersionLen = 256
+
// semVerRegex is the regular expression used to parse a semantic version.
// This is not the official regex from the semver spec. It has been modified to allow for loose handling
// where versions like 2.1 are detected.
@@ -94,6 +103,10 @@ func StrictNewVersion(v string) (*Version, error) {
return nil, ErrEmptyString
}
+ if len(v) > MaxVersionLen {
+ return nil, ErrVersionTooLong
+ }
+
// Split the parts into [0]major, [1]minor, and [2]patch,prerelease,build
parts := strings.SplitN(v, ".", 3)
if len(parts) != 3 {
@@ -161,6 +174,9 @@ func StrictNewVersion(v string) (*Version, error) {
// attempts to convert it to SemVer. If you want to validate it was a strict
// semantic version at parse time see StrictNewVersion().
func NewVersion(v string) (*Version, error) {
+ if len(v) > MaxVersionLen {
+ return nil, ErrVersionTooLong
+ }
if CoerceNewVersion {
return coerceNewVersion(v)
}
@@ -289,6 +305,8 @@ func coerceNewVersion(v string) (*Version, error) {
// New creates a new instance of Version with each of the parts passed in as
// arguments instead of parsing a version string.
+// Note, New does not validate prerelease or metadata. Incorrect information can
+// be passed in.
func New(major, minor, patch uint64, pre, metadata string) *Version {
v := Version{
major: major,
@@ -301,6 +319,7 @@ func New(major, minor, patch uint64, pre, metadata string) *Version {
v.original = v.String()
+ // TODO: In the next semver major version validate the pre and metadata. Return error if there is one.
return &v
}
@@ -388,6 +407,9 @@ func (v Version) IncPatch() Version {
} else {
vNext.metadata = ""
vNext.pre = ""
+ if v.patch == math.MaxUint64 {
+ panic("patch version increment would overflow uint64")
+ }
vNext.patch = v.patch + 1
}
vNext.original = v.originalVPrefix() + "" + vNext.String()
@@ -404,6 +426,9 @@ func (v Version) IncMinor() Version {
vNext.metadata = ""
vNext.pre = ""
vNext.patch = 0
+ if v.minor == math.MaxUint64 {
+ panic("minor version increment would overflow uint64")
+ }
vNext.minor = v.minor + 1
vNext.original = v.originalVPrefix() + "" + vNext.String()
return vNext
@@ -421,6 +446,9 @@ func (v Version) IncMajor() Version {
vNext.pre = ""
vNext.patch = 0
vNext.minor = 0
+ if v.major == math.MaxUint64 {
+ panic("major version increment would overflow uint64")
+ }
vNext.major = v.major + 1
vNext.original = v.originalVPrefix() + "" + vNext.String()
return vNext
@@ -568,7 +596,16 @@ func (v Version) MarshalText() ([]byte, error) {
// Scan implements the SQL.Scanner interface.
func (v *Version) Scan(value interface{}) error {
var s string
- s, _ = value.(string)
+ switch t := value.(type) {
+ case string:
+ s = t
+ case []byte:
+ s = string(t)
+ case nil:
+ return fmt.Errorf("cannot scan nil into Version")
+ default:
+ return fmt.Errorf("unsupported Scan type %T", value)
+ }
temp, err := NewVersion(s)
if err != nil {
return err
diff --git a/vendor/github.com/alecthomas/chroma/v2/.golangci.yml b/vendor/github.com/alecthomas/chroma/v2/.golangci.yml
index 91f313b1..a345ac65 100644
--- a/vendor/github.com/alecthomas/chroma/v2/.golangci.yml
+++ b/vendor/github.com/alecthomas/chroma/v2/.golangci.yml
@@ -1,89 +1,122 @@
+version: "2"
run:
tests: true
-
output:
- print-issued-lines: false
-
+ show-stats: false
+ formats:
+ text:
+ print-issued-lines: false
+ colors: true
linters:
- enable-all: true
+ default: all
disable:
- - lll
- - gocyclo
+ - exhaustive
+ - prealloc
- dupl
- - gochecknoglobals
- - funlen
- - godox
- - wsl
- - gocognit
- - nolintlint
- - testpackage
- - godot
- - nestif
- - paralleltest
- - nlreturn
+ - godoclint
- cyclop
- - gci
- - gofumpt
- - errorlint
- - exhaustive
- - wrapcheck
- - stylecheck
- - thelper
- - nonamedreturns
- - revive
+ - depguard
- dupword
+ - err113
+ - errname
+ - errorlint
- exhaustruct
- - varnamelen
+ - forbidigo
- forcetypeassert
+ - funlen
+ - gochecknoglobals
+ - gocognit
+ - gocritic
+ - gocyclo
+ - godot
+ - godox
+ - gomoddirectives
- ireturn
+ - lll
- maintidx
- - govet
- - testableexamples
- - musttag
- - depguard
- - goconst
- - perfsprint
- mnd
+ - nakedret
+ - nestif
+ - nilnil
+ - nlreturn
+ - nolintlint
+ - nonamedreturns
+ - paralleltest
+ - perfsprint
- predeclared
- recvcheck
- - tenv
- - err113
-
-linters-settings:
- gocyclo:
- min-complexity: 10
- dupl:
- threshold: 100
- goconst:
- min-len: 8
- min-occurrences: 3
- forbidigo:
- #forbid:
- # - (Must)?NewLexer$
- exclude_godoc_examples: false
-
-
+ - revive
+ - testpackage
+ - varnamelen
+ - wastedassign
+ - whitespace
+ - wsl
+ - wsl_v5
+ - funcorder
+ - noinlineerr
+ - tagalign
+ - goconst
+ - gochecknoinits
+ - durationcheck
+ - embeddedstructfieldcheck
+ - wrapcheck
+ - gomodguard
+ settings:
+ dupl:
+ threshold: 100
+ exhaustive:
+ default-signifies-exhaustive: true
+ goconst:
+ min-len: 8
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 10
+ wrapcheck:
+ report-internal-errors: false
+ ignore-package-globs:
+ - github.com/alecthomas/errors
+ exclusions:
+ generated: lax
+ rules:
+ - path: (.+)\.go$
+ text: "^(G104|G204|G307|G304):"
+ - path: (.+)\.go$
+ text: Error return value of .(.*\.Help|.*\.MarkFlagRequired|(os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked
+ - path: (.+)\.go$
+ text: exported method `(.*\.MarshalJSON|.*\.UnmarshalJSON|.*\.EntityURN|.*\.GoString|.*\.Pos)` should have comment or be unexported
+ - path: (.+)\.go$
+ text: uses unkeyed fields
+ - path: (.+)\.go$
+ text: declaration of "err" shadows declaration
+ - path: (.+)\.go$
+ text: bad syntax for struct tag key
+ - path: (.+)\.go$
+ text: bad syntax for struct tag pair
+ - path: (.+)\.go$
+ text: ^ST1012
+ - path: (.+)\.go$
+ text: log/slog.Logger.*must not be called
+ - path: (.+)_test\.go$
+ text: error returned from external package is unwrapped
+ - linters: [staticcheck]
+ text: QF1008
+ - text: "Error return value of `.*.Write` is not checked"
+ linters: [errcheck]
+ path: (.+)_test\.go$
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
issues:
- exclude-dirs:
- - _examples
- max-per-linter: 0
- max-same: 0
- exclude-use-default: false
- exclude:
- # Captured by errcheck.
- - '^(G104|G204):'
- # Very commonly not checked.
- - 'Error return value of .(.*\.Help|.*\.MarkFlagRequired|(os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked'
- - 'exported method (.*\.MarshalJSON|.*\.UnmarshalJSON|.*\.EntityURN|.*\.GoString|.*\.Pos) should have comment or be unexported'
- - 'composite literal uses unkeyed fields'
- - 'declaration of "err" shadows declaration'
- - 'should not use dot imports'
- - 'Potential file inclusion via variable'
- - 'should have comment or be unexported'
- - 'comment on exported var .* should be of the form'
- - 'at least one file in a package should have a package comment'
- - 'string literal contains the Unicode'
- - 'methods on the same type should have the same receiver name'
- - '_TokenType_name should be _TokenTypeName'
- - '`_TokenType_map` should be `_TokenTypeMap`'
- - 'rewrite if-else to switch statement'
+ max-issues-per-linter: 0
+ max-same-issues: 0
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ exclusions:
+ generated: lax
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
diff --git a/vendor/github.com/alecthomas/chroma/v2/AGENTS.md b/vendor/github.com/alecthomas/chroma/v2/AGENTS.md
index 0d3b6ee4..d15d770a 100644
--- a/vendor/github.com/alecthomas/chroma/v2/AGENTS.md
+++ b/vendor/github.com/alecthomas/chroma/v2/AGENTS.md
@@ -1,6 +1,6 @@
Chroma is a syntax highlighting library, tool and web playground for Go. It is based on Pygments and includes importers for it, so most of the same concepts from Pygments apply to Chroma.
-This project is written in Go, uses Hermit to manage tooling, and Just for helper commands. Helper scripts are in ./scripts.
+This project is written in Go, uses Hermit to manage tooling, and Just for helper commands. Helper tooling is primarily in ./_tools.
Language definitions are XML files defined in ./lexers/embedded/*.xml.
diff --git a/vendor/github.com/alecthomas/chroma/v2/BUILD.bit b/vendor/github.com/alecthomas/chroma/v2/BUILD.bit
new file mode 100644
index 00000000..f8ee1aee
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/BUILD.bit
@@ -0,0 +1,93 @@
+let version = exec("git describe --tags --dirty --always") | trim
+# TinyGo's installation root; used to source `wasm_exec.js`.
+let tinygoroot = exec("tinygo env TINYGOROOT") | trim
+
+
+# Generate tokentype_enumer.go from types.go via `//go:generate`.
+tokentype = go.generate {
+ package = "."
+ inputs = ["types.go"]
+ outputs = ["tokentype_enumer.go"]
+}
+
+# Regenerate the lexer table in README.md by invoking the host `chroma` binary.
+# GOOS/GOARCH are cleared so cross-compile env vars don't break the local run.
+protected readme = exec {
+ command = "./table.py"
+ inputs = ["table.py", "lexers/**/*.go", "lexers/**/*.xml"]
+ output = "README.md"
+}
+
+# Format frontend JS sources in place. Runs as a sub-step of `index-min-js`,
+# so bundling always sees formatted sources.
+format-js = exec {
+ command = "biome format --write cmd/chromad/static/index.js cmd/chromad/static/chroma.js"
+ inputs = ["biome.js", "cmd/chromad/static/index.js", "cmd/chromad/static/chroma.js"]
+}
+
+# Copy TinyGo's wasm_exec.js into the chromad static assets.
+wasm-exec = exec {
+ command = "install -m644 '#{tinygoroot}/targets/wasm_exec.js' cmd/chromad/static/wasm_exec.js"
+ resolve = "sha256 '#{tinygoroot}/targets/wasm_exec.js'"
+ output = "cmd/chromad/static/wasm_exec.js"
+}
+
+# Build the chroma WASM module via tinygo (installed via hermit) for the
+# smaller output binary.
+chroma-wasm = exec {
+ command = "tinygo build -no-debug -target wasm -o cmd/chromad/static/chroma.wasm cmd/libchromawasm/main.go"
+ inputs = ["cmd/libchromawasm/**/*.go", "*.go", "lexers/**/*.go", "lexers/**/*.xml", "formatters/**/*.go", "styles/**/*.go"]
+ output = "cmd/chromad/static/chroma.wasm"
+}
+
+# Bundle and minify the frontend JS. Depends on `format-js` so the bundle
+# always reflects formatted sources.
+index-min-js = exec {
+ command = "esbuild --platform=browser --format=esm --bundle cmd/chromad/static/index.js --minify --external:./wasm_exec.js --outfile=cmd/chromad/static/index.min.js"
+ inputs = ["cmd/chromad/static/index.js", "cmd/chromad/static/chroma.js"]
+ output = "cmd/chromad/static/index.min.js"
+ depends_on = [format-js]
+}
+
+# Bundle and minify the frontend CSS.
+index-min-css = exec {
+ command = "esbuild --bundle cmd/chromad/static/index.css --minify --outfile=cmd/chromad/static/index.min.css"
+ inputs = ["cmd/chromad/static/index.css", "cmd/chromad/static/bulma.css"]
+ output = "cmd/chromad/static/index.min.css"
+}
+
+# Build the chromad server binary. cmd/chromad is a separate Go module, so
+# `dir` puts the build in there and `package = "."` resolves against that
+# module. `output` stays project-root-relative; bit absolutises it before
+# passing to `go build -o`. Defaults to linux/amd64 to match the deploy
+# target; override with GOOS/GOARCH env vars for local builds.
+chromad = go.exe {
+ dir = "cmd/chromad"
+ package = "."
+ output = "build/chromad"
+ flags = ["-ldflags", "-X 'main.version=#{version}'"]
+ goos = env("GOOS", "linux")
+ goarch = env("GOARCH", "amd64")
+ cgo = false
+ depends_on = [wasm-exec, chroma-wasm, index-min-js, index-min-css, test]
+}
+
+pre format-go = go.fmt {
+ package = "./..."
+}
+
+# Run Go tests.
+test = go.test {
+ package = "./..."
+}
+
+# Deploy chromad to swapoff.org. Must be explicitly selected.
+explicit upload = exec {
+ command = <<-EOF
+ scp #{chromad.path} root@swapoff.org:
+ ssh root@swapoff.org 'install -m755 ./chromad /srv/http/swapoff.org/bin && service chromad restart'
+ EOF
+ depends_on = [chromad]
+}
+
+target default = [test, chromad, readme, tokentype]
diff --git a/vendor/github.com/alecthomas/chroma/v2/Bitfile b/vendor/github.com/alecthomas/chroma/v2/Bitfile
deleted file mode 100644
index bf158633..00000000
--- a/vendor/github.com/alecthomas/chroma/v2/Bitfile
+++ /dev/null
@@ -1,24 +0,0 @@
-VERSION = %(git describe --tags --dirty --always)%
-export CGOENABLED = 0
-
-tokentype_enumer.go: types.go
- build: go generate
-
-# Regenerate the list of lexers in the README
-README.md: lexers/*.go lexers/*/*.xml table.py
- build: ./table.py
- -clean
-
-implicit %{1}%{2}.min.%{3}: **/*.{css,js}
- build: esbuild --bundle %{IN} --minify --outfile=%{OUT}
-
-implicit build/%{1}: cmd/*
- cd cmd/%{1}
- inputs: cmd/%{1}/**/* **/*.go
- build: go build -ldflags="-X 'main.version=%{VERSION}'" -o ../../build/%{1} .
-
-#upload: chromad
-# build:
-# scp chromad root@swapoff.org:
-# ssh root@swapoff.org 'install -m755 ./chromad /srv/http/swapoff.org/bin && service chromad restart'
-# touch upload
diff --git a/vendor/github.com/alecthomas/chroma/v2/COPYING b/vendor/github.com/alecthomas/chroma/v2/COPYING
index 92dc39f7..33da4898 100644
--- a/vendor/github.com/alecthomas/chroma/v2/COPYING
+++ b/vendor/github.com/alecthomas/chroma/v2/COPYING
@@ -17,3 +17,102 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+
+
+// formatters/svg/font_liberation_mono.go
+
+Digitized data copyright (c) 2010 Google Corporation
+with Reserved Font Arimo, Tinos and Cousine.
+Copyright (c) 2012 Red Hat, Inc.
+with Reserved Font Name Liberation.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+https://openfontlicense.org
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/vendor/github.com/alecthomas/chroma/v2/Dockerfile b/vendor/github.com/alecthomas/chroma/v2/Dockerfile
index c86b3793..dc10ec75 100644
--- a/vendor/github.com/alecthomas/chroma/v2/Dockerfile
+++ b/vendor/github.com/alecthomas/chroma/v2/Dockerfile
@@ -1,7 +1,7 @@
# Multi-stage Dockerfile for chromad Go application using Hermit-managed tools
# Build stage
-FROM ubuntu:24.04 AS builder
+FROM ubuntu:26.04 AS builder
# Install system dependencies
RUN apt-get update && apt-get install -y \
@@ -28,7 +28,7 @@ ENV GOARCH=amd64
RUN just chromad
# Runtime stage
-FROM alpine:3.23 AS runtime
+FROM alpine:3.24 AS runtime
# Install ca-certificates for HTTPS requests
RUN apk --no-cache add ca-certificates curl
diff --git a/vendor/github.com/alecthomas/chroma/v2/Justfile b/vendor/github.com/alecthomas/chroma/v2/Justfile
index 24e3816f..4db3dc31 100644
--- a/vendor/github.com/alecthomas/chroma/v2/Justfile
+++ b/vendor/github.com/alecthomas/chroma/v2/Justfile
@@ -1,4 +1,4 @@
-set positional-arguments := true
+set positional-arguments
set shell := ["bash", "-c"]
version := `git describe --tags --dirty --always`
@@ -21,6 +21,10 @@ tokentype-string:
format-js:
biome format --write cmd/chromad/static/index.js cmd/chromad/static/chroma.js
+# Tidy Go modules
+tidy:
+ find . -name 'go.mod' -execdir go mod tidy \;
+
# Build chromad binary
chromad: wasm-exec chroma-wasm
#!/usr/bin/env bash
diff --git a/vendor/github.com/alecthomas/chroma/v2/README.md b/vendor/github.com/alecthomas/chroma/v2/README.md
index 4aeb54d9..df962da7 100644
--- a/vendor/github.com/alecthomas/chroma/v2/README.md
+++ b/vendor/github.com/alecthomas/chroma/v2/README.md
@@ -36,25 +36,25 @@ translators for Pygments lexers and styles.
| Prefix | Language
| :----: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, ATL, AutoHotkey, AutoIt, Awk
+| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, AMPL, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, Arturo, ATL, AutoHotkey, AutoIt, Awk
| B | Ballerina, Bash, Bash Session, Batchfile, Beef, BibTeX, Bicep, BlitzBasic, BNF, BQN, Brainfuck
| C | C, C#, C++, C3, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Core, Crystal, CSS, CSV, CUE, Cython
-| D | D, Dart, Dax, Desktop file, Diff, Django/Jinja, dns, Docker, DTD, Dylan
-| E | EBNF, Elixir, Elm, EmacsLisp, Erlang
+| D | D, Dart, Dax, Desktop file, Devicetree, Diff, Django/Jinja, dns, Docker, DTD, Dylan
+| E | EBNF, Elixir, Elm, EmacsLisp, ERB, Erlang
| F | Factor, Fennel, Fish, Forth, Fortran, FortranFixed, FSharp
-| G | GAS, GDScript, GDScript3, Gemtext, Genshi, Genshi HTML, Genshi Text, Gherkin, Gleam, GLSL, Gnuplot, Go, Go HTML Template, Go Template, Go Text Template, GraphQL, Groff, Groovy
+| G | GAS, GDScript, GDScript3, Gemtext, Genshi, Genshi HTML, Genshi Text, Gettext, Gherkin, Gleam, GLSL, Gnuplot, Go, Go HTML Template, Go Template, Go Text Template, GraphQL, Groff, Groovy
| H | Handlebars, Hare, Haskell, Haxe, HCL, Hexdump, HLB, HLSL, HolyC, HTML, HTTP, Hy
| I | Idris, Igor, INI, Io, ISCdhcpd
| J | J, Janet, Java, JavaScript, JSON, JSONata, Jsonnet, Julia, Jungle
-| K | Kakoune, Kotlin
-| L | Lean4, Lighttpd configuration file, LLVM, lox, Lua
-| M | Makefile, Mako, markdown, Markless, Mason, Materialize SQL dialect, Mathematica, Matlab, MCFunction, Meson, Metal, MiniZinc, MLIR, Modelica, Modula-2, Mojo, MonkeyC, MoonScript, MorrowindScript, Myghty, MySQL
+| K | Kakoune, KDL, Kotlin
+| L | Lateralus, Lean4, Lighttpd configuration file, LilyPond, LLVM, lox, Lua, Luau
+| M | Makefile, Mako, markdown, Markless, Mason, Materialize SQL dialect, Mathematica, Matlab, MCFunction, Meson, Metal, microcad, MiniZinc, MLIR, Modelica, Modula-2, Mojo, MonkeyC, MoonBit, MoonScript, MorrowindScript, Myghty, MySQL
| N | NASM, Natural, NDISASM, Newspeak, Nginx configuration file, Nim, Nix, NSIS, Nu
| O | Objective-C, ObjectPascal, OCaml, Octave, Odin, OnesEnterprise, OpenEdge ABL, OpenSCAD, Org Mode
| P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Plutus Core, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerQuery, PowerShell, Prolog, Promela, PromQL, properties, Protocol Buffer, Protocol Buffer Text Format, PRQL, PSL, Puppet, Python, Python 2
| Q | QBasic, QML
| R | R, Racket, Ragel, Raku, react, ReasonML, reg, Rego, reStructuredText, Rexx, RGBDS Assembly, Ring, RPGLE, RPMSpec, Ruby, Rust
-| S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Sed, Sieve, Smali, Smalltalk, Smarty, SNBT, Snobol, Solidity, SourcePawn, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog
+| S | SAS, Sass, Scala, scdoc, Scheme, Scilab, SCSS, Sed, Sieve, Smali, Smalltalk, Smarty, SNBT, Snobol, Solidity, SourcePawn, Spade, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog
| T | TableGen, Tal, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData, Typst
| U | ucode
| V | V, V shell, Vala, VB.net, verilog, VHDL, VHS, VimL, vue
@@ -226,11 +226,11 @@ formatter outputs raw tokens. The latter is useful for debugging lexers.
### Styles
Chroma styles are defined in XML. The style entries use the
-[same syntax](http://pygments.org/docs/styles/) as Pygments.
-
-All Pygments styles have been converted to Chroma using the `_tools/style.py`
+[same syntax](http://pygments.org/docs/styles/) as Pygments. All Pygments styles have been converted to Chroma using the `_tools/style.py`
script.
+Style names are case-insensitive. For example, `monokai` and `Monokai` are treated as the same style.
+
When you work with one of [Chroma's styles](https://github.com/alecthomas/chroma/tree/master/styles),
know that the `Background` token type provides the default style for tokens. It does so
by defining a foreground color and background color.
@@ -276,6 +276,8 @@ for that setup the `chroma` executable can be just symlinked to `~/.lessfilter`.
its input using Chroma
* [Hugo](https://gohugo.io/) is a static site generator that [uses Chroma for syntax
highlighting code examples](https://gohugo.io/content-management/syntax-highlighting/)
+* [f4](https://github.com/unxed/f4) is asynchronious cross platform Far Manager clone in Go
+ that uses Chroma for syntax highlighting in built-in editor
## Testing lexers
diff --git a/vendor/github.com/alecthomas/chroma/v2/colour.go b/vendor/github.com/alecthomas/chroma/v2/colour.go
index e33d0106..8add068d 100644
--- a/vendor/github.com/alecthomas/chroma/v2/colour.go
+++ b/vendor/github.com/alecthomas/chroma/v2/colour.go
@@ -52,7 +52,7 @@ type Colour int32
// NewColour creates a Colour directly from RGB values.
func NewColour(r, g, b uint8) Colour {
- return ParseColour(fmt.Sprintf("%02x%02x%02x", r, g, b))
+ return Colour(int32(r)<<16|int32(g)<<8|int32(b)) + 1
}
// Distance between this colour and another.
diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go b/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go
index 1aaafd0f..e876aab7 100644
--- a/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go
+++ b/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go
@@ -4,6 +4,7 @@ import (
"fmt"
"html"
"io"
+ "slices"
"sort"
"strconv"
"strings"
@@ -83,6 +84,11 @@ func WithPreWrapper(wrapper PreWrapper) Option {
}
}
+// WithModeClasses adds the style's mode (eg. "light" or "dark") as a CSS
+// class on wrapper elements and scopes WriteCSS rules by mode. This enables
+// combining light and dark stylesheets and switching themes at runtime.
+func WithModeClasses(b bool) Option { return func(f *Formatter) { f.modeClasses = b } }
+
// WrapLongLines wraps long lines.
func WrapLongLines(b bool) Option {
return func(f *Formatter) {
@@ -206,6 +212,7 @@ type Formatter struct {
inlineCode bool
preventSurroundingPre bool
tabWidth int
+ modeClasses bool
wrapLongLines bool
lineNumbers bool
lineNumbersInTable bool
@@ -241,7 +248,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
fmt.Fprintf(w, "body { %s; }\n", css[chroma.Background])
fmt.Fprint(w, "")
}
- fmt.Fprintf(w, "\n", f.styleAttr(css, chroma.Background))
+ fmt.Fprintf(w, "\n", f.styleAttrWithMode(css, chroma.Background, style))
}
wrapInTable := f.lineNumbers && f.lineNumbersInTable
@@ -252,10 +259,10 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
if wrapInTable {
// List line numbers in its own
\n", f.styleAttr(css, chroma.LineTableTD))
- fmt.Fprintf(w, "%s", f.preWrapper.Start(false, f.styleAttr(css, chroma.PreWrapper)))
+ fmt.Fprintf(w, "%s", f.preWrapper.Start(false, f.styleAttrWithMode(css, chroma.PreWrapper, style)))
for index := range lines {
line := f.baseLineNumber + index
highlight, next := f.shouldHighlight(highlightIndex, line)
@@ -277,7 +284,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
fmt.Fprintf(w, "
\n", f.styleAttr(css, chroma.LineTableTD, "width:100%"))
}
- fmt.Fprintf(w, "%s", f.preWrapper.Start(true, f.styleAttr(css, chroma.PreWrapper)))
+ fmt.Fprintf(w, "%s", f.preWrapper.Start(true, f.styleAttrWithMode(css, chroma.PreWrapper, style)))
highlightIndex = 0
for index, tokens := range lines {
@@ -288,7 +295,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
highlightIndex++
}
- if !(f.preventSurroundingPre || f.inlineCode) {
+ if !f.preventSurroundingPre && !f.inlineCode {
// Start of Line
fmt.Fprint(w, ``) // End of CodeLine
fmt.Fprint(w, ``) // End of Line
@@ -414,6 +421,26 @@ func (f *Formatter) styleAttr(styles map[chroma.TokenType]string, tt chroma.Toke
return fmt.Sprintf(` style="%s"`, strings.Join(css, ";"))
}
+// modeClass returns the CSS class corresponding to the style's mode (eg.
+// "light" or "dark"), with the formatter's class prefix applied.
+func (f *Formatter) modeClass(style *chroma.Style) string {
+ return f.prefix + style.Mode().String()
+}
+
+// styleAttrWithMode is like styleAttr but, in classes mode, appends the
+// style's mode class alongside the existing class. Used for the outer
+// wrapper and standalone so external CSS can target the mode.
+func (f *Formatter) styleAttrWithMode(styles map[chroma.TokenType]string, tt chroma.TokenType, style *chroma.Style) string {
+ if !f.Classes || !f.modeClasses {
+ return f.styleAttr(styles, tt)
+ }
+ cls := f.class(tt)
+ if cls == "" {
+ return ""
+ }
+ return fmt.Sprintf(` class="%s %s"`, cls, f.modeClass(style))
+}
+
func (f *Formatter) tabWidthStyle() string {
if f.tabWidth != 0 && f.tabWidth != 8 {
return fmt.Sprintf("-moz-tab-size: %[1]d; -o-tab-size: %[1]d; tab-size: %[1]d;", f.tabWidth)
@@ -437,20 +464,38 @@ func (f *Formatter) writeCSSRule(w io.Writer, comment string, selector string, s
}
// WriteCSS writes CSS style definitions (without any surrounding HTML).
+//
+// Rules are scoped by the style's mode (eg. ".chroma.dark") so that CSS
+// generated from a light and dark style can be combined without conflict.
+// To support dynamic theme switching, call WriteCSS with both styles,
+// concatenate the output, and toggle the wrapper's mode class (added
+// automatically by Format) at runtime. Tokens that one theme leaves
+// unstyled fall back to that theme's ".chroma." text/background
+// via the CSS cascade; pass WithAllClasses(true) if you need every
+// token's rule materialised explicitly for both themes.
func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
css := f.styleCache.get(style, false)
+ var chromaSel, bgSel string
+ if f.modeClasses {
+ modeCls := f.modeClass(style)
+ chromaSel = fmt.Sprintf(".%schroma.%s", f.prefix, modeCls)
+ bgSel = fmt.Sprintf(".%sbg.%s", f.prefix, modeCls)
+ } else {
+ chromaSel = fmt.Sprintf(".%schroma", f.prefix)
+ bgSel = fmt.Sprintf(".%sbg", f.prefix)
+ }
// Special-case background as it is mapped to the outer ".chroma" class.
- if err := f.writeCSSRule(w, chroma.Background.String(), fmt.Sprintf(".%sbg", f.prefix), css[chroma.Background]); err != nil {
+ if err := f.writeCSSRule(w, chroma.Background.String(), bgSel, css[chroma.Background]); err != nil {
return err
}
// Special-case PreWrapper as it is the ".chroma" class.
- if err := f.writeCSSRule(w, chroma.PreWrapper.String(), fmt.Sprintf(".%schroma", f.prefix), css[chroma.PreWrapper]); err != nil {
+ if err := f.writeCSSRule(w, chroma.PreWrapper.String(), chromaSel, css[chroma.PreWrapper]); err != nil {
return err
}
// Special-case code column of table to expand width.
if f.lineNumbers && f.lineNumbersInTable {
- selector := fmt.Sprintf(".%schroma .%s:last-child", f.prefix, f.class(chroma.LineTableTD))
+ selector := fmt.Sprintf("%s .%s:last-child", chromaSel, f.class(chroma.LineTableTD))
if err := f.writeCSSRule(w, chroma.LineTableTD.String(), selector, "width: 100%;"); err != nil {
return err
}
@@ -460,7 +505,7 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
targetedLineCSS := StyleEntryToCSS(style.Get(chroma.LineHighlight))
for _, tt := range []chroma.TokenType{chroma.LineNumbers, chroma.LineNumbersTable} {
comment := fmt.Sprintf("%s targeted by URL anchor", tt)
- selector := fmt.Sprintf(".%schroma .%s:target", f.prefix, f.class(tt))
+ selector := fmt.Sprintf("%s .%s:target", chromaSel, f.class(tt))
if err := f.writeCSSRule(w, comment, selector, targetedLineCSS); err != nil {
return err
}
@@ -481,7 +526,7 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
if class == "" {
continue
}
- if err := f.writeCSSRule(w, tt.String(), fmt.Sprintf(".%schroma .%s", f.prefix, class), css[tt]); err != nil {
+ if err := f.writeCSSRule(w, tt.String(), fmt.Sprintf("%s .%s", chromaSel, class), css[tt]); err != nil {
return err
}
}
@@ -613,8 +658,7 @@ func (l *styleCache) get(style *chroma.Style, compress bool) map[chroma.TokenTyp
defer l.mu.Unlock()
// Look for an existing entry.
- for i := len(l.cache) - 1; i >= 0; i-- {
- entry := l.cache[i]
+ for i, entry := range slices.Backward(l.cache) {
if entry.style == style && entry.compressed == compress {
// Top of the cache, no need to adjust the order.
if i == len(l.cache)-1 {
diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go b/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go
index 70d692ec..416208a7 100644
--- a/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go
+++ b/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go
@@ -4,7 +4,7 @@
// with Reserved Font Name Liberation.
//
// This Font Software is licensed under the SIL Open Font License, Version 1.1.
-// This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+// This license is copied below, and is also available with a FAQ at: https://openfontlicense.org
//
// -----------------------------------------------------------
// SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml
new file mode 100644
index 00000000..8c2479e5
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml
@@ -0,0 +1,98 @@
+
+
+ AMPL
+ ampl
+ *.mod
+ *.run
+ text/x-ampl
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arturo.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arturo.xml
new file mode 100644
index 00000000..541dc46e
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arturo.xml
@@ -0,0 +1,119 @@
+
+
+
+ Arturo
+ arturo
+ art
+ *.art
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3
+ 5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml
index f1b454fa..4044f491 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml
@@ -81,7 +81,7 @@
-
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml
new file mode 100644
index 00000000..e597cd8a
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml
@@ -0,0 +1,37 @@
+
+
+ ERB
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml
index 7557bce0..399cdd00 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml
@@ -56,7 +56,7 @@
-
+
@@ -114,7 +114,7 @@
-
+
@@ -139,7 +139,7 @@
-
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gemfile_lock.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gemfile_lock.xml
new file mode 100644
index 00000000..83fc47b7
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gemfile_lock.xml
@@ -0,0 +1,81 @@
+
+
+ Gemfile.lock
+ gemfile-lock
+ gemfilelock
+ Gemfile.lock
+ *.gemfile.lock
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml
new file mode 100644
index 00000000..38c0c21b
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml
@@ -0,0 +1,24 @@
+
+
+
+ Gettext
+ pot
+ po
+ *.pot
+ *.po
+ application/x-gettext
+ text/x-gettext
+ text/gettext
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml
index b0622735..b40422f2 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml
@@ -76,6 +76,10 @@
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml
index 3ce33ff6..4ef5fd26 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml
@@ -32,7 +32,7 @@
pattern="(assert|break|case|catch|continue|default|do|else|finally|for|if|goto|instanceof|new|return|switch|this|throw|try|while)\b">
-
+
@@ -44,7 +44,7 @@
+ pattern="(abstract|const|enum|exports|extends|final|implements|native|non-sealed|open|opens|permits|private|protected|provides|public|requires|sealed|static|strictfp|super|synchronized|throws|to|transient|transitive|uses|volatile|with|yield)\b">
@@ -64,6 +64,10 @@
+
+
+
+
@@ -71,7 +75,7 @@
-
+
@@ -147,6 +151,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml
index efe80ed3..0e475c53 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml
@@ -133,7 +133,7 @@
-
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml
index a34abfa4..f65d7103 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml
@@ -2,10 +2,15 @@
JSONjson
+ jsonl*.json
+ *.jsonl*.jsonc
+ *.json5*.avsc
+ .luaurcapplication/json
+ application/jsonltruetrue
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml
new file mode 100644
index 00000000..cea10eba
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml
@@ -0,0 +1,184 @@
+
+
+ Lateralus
+ lateralus
+ ltl
+ *.ltl
+ text/x-lateralus
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lilypond.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lilypond.xml
new file mode 100644
index 00000000..fe4ac8ed
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lilypond.xml
@@ -0,0 +1,133 @@
+
+
+
+ LilyPond
+ lilypond
+ *.ly
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml
index e3d778f1..903d4581 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml
@@ -2,10 +2,8 @@
Lualua
- luau*.lua*.wlua
- *.luautext/x-luaapplication/x-lua
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml
new file mode 100644
index 00000000..79a60949
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml
@@ -0,0 +1,173 @@
+
+
+ Luau
+ luau
+ *.luau
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml
index 7094ddc3..616d7ae4 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml
@@ -45,7 +45,7 @@
-
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml
index 130047df..fcfbda11 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml
@@ -4,6 +4,7 @@
mesonmeson.buildmeson.build
+ meson.optionsmeson_options.txttext/x-meson
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml
index b6c2046d..0517ec8f 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml
@@ -38,7 +38,7 @@
-
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nu.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nu.xml
index 32655808..82d4b375 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nu.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nu.xml
@@ -3,7 +3,12 @@
Nunu*.nu
+ application/x-shellscripttext/plain
+ text/x-shellscript
+
+
+
@@ -118,4 +123,4 @@
-
+
\ No newline at end of file
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml
index c9e22ea5..774bb79b 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml
@@ -54,7 +54,7 @@
-
+
@@ -82,12 +82,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -101,6 +135,10 @@
+
+
+
+
@@ -116,7 +154,7 @@
-
+
@@ -132,6 +170,13 @@
+
+
+
+
+
+
+
@@ -161,7 +206,7 @@
-
+
@@ -170,8 +215,9 @@
-
+
+
@@ -185,7 +231,7 @@
-
+
@@ -194,7 +240,7 @@
-
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml
index 15a3422d..32d1bb08 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml
@@ -5,6 +5,10 @@
postscr*.ps*.eps
+ *.epsf
+ *.epsi
+ *.pfa
+ *.t42application/postscript
@@ -86,4 +90,4 @@
-
\ No newline at end of file
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml
index 157d321f..f8f0c8d7 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml
@@ -7,7 +7,7 @@
-
+
@@ -16,7 +16,7 @@
-
+
@@ -34,7 +34,7 @@
-
+
@@ -46,9 +46,12 @@
-
+
+
+
+
@@ -62,6 +65,9 @@
+
+
+
@@ -69,7 +75,7 @@
-
+
@@ -115,4 +121,4 @@
-
\ No newline at end of file
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml
index baa7e435..15e96ba8 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml
@@ -12,7 +12,11 @@
*.rbx*.dubyGemfile
+ *.gemfileVagrantfile
+ Appraisals
+ .pryrc
+ *.json.jbuildertext/x-rubyapplication/x-rubytrue
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml
new file mode 100644
index 00000000..1b3a876e
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml
@@ -0,0 +1,115 @@
+
+
+ scdoc
+ scdoc
+ *.scd
+ *.scdoc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml
new file mode 100644
index 00000000..4dfe3292
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml
@@ -0,0 +1,292 @@
+
+
+ Spade
+ spade
+ *.spade
+ text/spade
+ text/x-spade
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/templ.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/templ.xml
new file mode 100644
index 00000000..14c26d6b
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/templ.xml
@@ -0,0 +1,315 @@
+
+
+ Templ
+ templ
+ *.templ
+ text/x-templ
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml
index a3e3be23..b39c9649 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml
@@ -226,7 +226,7 @@
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml
index 2c6a4d99..99d5d530 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml
@@ -10,6 +10,7 @@
*.wsdl*.wsf*.svg
+ *.qrc*.csproj*.vcxproj*.fsproj
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml
index 07075541..ede15d33 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml
@@ -23,6 +23,9 @@
+
+
+
@@ -78,15 +81,22 @@
+
+
+
+
+
+
+
-
+
-
+
@@ -95,14 +105,14 @@
-
+
-
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/erb.go b/vendor/github.com/alecthomas/chroma/v2/lexers/erb.go
new file mode 100644
index 00000000..2d141ed9
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/erb.go
@@ -0,0 +1,29 @@
+package lexers
+
+import (
+ "strings"
+
+ . "github.com/alecthomas/chroma/v2" // nolint
+)
+
+// ERB lexer is Ruby embedded in HTML.
+var ERB = Register(DelegatingLexer(HTML, MustNewXMLLexer(
+ embedded,
+ "embedded/erb.xml",
+).SetConfig(
+ &Config{
+ Name: "ERB",
+ Aliases: []string{"erb", "html+erb", "html+ruby", "rhtml"},
+ Filenames: []string{"*.erb", "*.html.erb", "*.xml.erb", "*.rhtml"},
+ MimeTypes: []string{"application/x-ruby-templating"},
+ DotAll: true,
+ },
+).SetAnalyser(func(text string) float32 {
+ if strings.Contains(text, "<%=") && strings.Contains(text, "%>") {
+ return 0.4
+ }
+ if strings.Contains(text, "<%") {
+ return 0.1
+ }
+ return 0.0
+})))
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/go.go b/vendor/github.com/alecthomas/chroma/v2/lexers/go.go
index c6123b90..e6e04cca 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/go.go
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/go.go
@@ -30,8 +30,8 @@ func goRules() Rules {
"root": {
{`\n`, TextWhitespace, nil},
{`\s+`, TextWhitespace, nil},
- {`//[^\s][^\n\r]*`, CommentPreproc, nil},
- {`//\s+[^\n\r]*`, CommentSingle, nil},
+ {`//[^\s\n\r][^\n\r]*`, CommentPreproc, nil},
+ {`//[^\n\r]*`, CommentSingle, nil},
{`/(\\\n)?[*](.|\n)*?[*](\\\n)?/`, CommentMultiline, nil},
{`(import|package)\b`, KeywordNamespace, nil},
{`(var|func|struct|map|chan|type|interface|const)\b`, KeywordDeclaration, nil},
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/http.go b/vendor/github.com/alecthomas/chroma/v2/lexers/http.go
index b57cb1b8..fee74d3b 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/http.go
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/http.go
@@ -122,7 +122,7 @@ func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (
if err != nil {
panic(err)
}
- return EOF
+ return subIterator()
}
}
}
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go b/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go
index bcd5b178..eed2cb7e 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go
@@ -1,11 +1,13 @@
package lexers
import (
+ "strings"
+
. "github.com/alecthomas/chroma/v2" // nolint
)
-// Markdown lexer.
-var Markdown = Register(MustNewLexer(
+// Markdown lexer with YAML frontmatter and HTML comment support.
+var Markdown = Register(&markdownLexer{Lexer: MustNewLexer(
&Config{
Name: "markdown",
Aliases: []string{"md", "mkd"},
@@ -13,11 +15,69 @@ var Markdown = Register(MustNewLexer(
MimeTypes: []string{"text/x-markdown"},
},
markdownRules,
-))
+)})
+
+// markdownLexer wraps the base Markdown lexer to highlight top-of-file YAML frontmatter.
+type markdownLexer struct {
+ Lexer
+}
+
+// Lexes Markdown, highlighting a leading YAML frontmatter block before delegating to Markdown rules.
+func (m *markdownLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
+ frontmatter, rest, ok := splitFrontmatter(text)
+ if !ok {
+ return m.Lexer.Tokenise(options, text)
+ }
+
+ yamlLexer := Get("YAML")
+ if yamlLexer == nil {
+ return m.Lexer.Tokenise(options, text)
+ }
+
+ yamlTokens, err := yamlLexer.Tokenise(options, frontmatter)
+ if err != nil {
+ return nil, err
+ }
+ markdownTokens, err := m.Lexer.Tokenise(options, rest)
+ if err != nil {
+ return nil, err
+ }
+ return Concaterator(yamlTokens, markdownTokens), nil
+}
+
+// Extracts a leading YAML frontmatter block if the document starts with one.
+func splitFrontmatter(text string) (frontmatter string, rest string, ok bool) {
+ if !strings.HasPrefix(text, "---\n") && !strings.HasPrefix(text, "---\r\n") {
+ return "", text, false
+ }
+
+ lineEnd := strings.IndexByte(text, '\n')
+ if lineEnd < 0 {
+ return "", text, false
+ }
+ if strings.TrimSuffix(text[:lineEnd], "\r") != "---" {
+ return "", text, false
+ }
+
+ for pos := lineEnd + 1; pos < len(text); {
+ next := strings.IndexByte(text[pos:], '\n')
+ if next < 0 {
+ break
+ }
+ lineEnd = pos + next
+ line := strings.TrimSuffix(text[pos:lineEnd], "\r")
+ if line == "---" {
+ return text[:lineEnd+1], text[lineEnd+1:], true
+ }
+ pos = lineEnd + 1
+ }
+ return "", text, false
+}
func markdownRules() Rules {
return Rules{
"root": {
+ {``, CommentMultiline, nil},
{`^(#[^#].+\n)`, ByGroups(GenericHeading), nil},
{`^(#{2,6}.+\n)`, ByGroups(GenericSubheading), nil},
{`^(\s*)([*-] )(\[[ xX]\])( .+\n)`, ByGroups(Text, Keyword, Keyword, UsingSelf("inline")), nil},
@@ -33,6 +93,7 @@ func markdownRules() Rules {
Include("inline"),
},
"inline": {
+ {``, CommentMultiline, nil},
{`\\.`, Text, nil},
{`(\s)(\*|_)((?:(?!\2).)*)(\2)((?=\W|\n))`, ByGroups(Text, GenericEmph, GenericEmph, GenericEmph, Text), nil},
{`(\s)((\*\*|__).*?)\3((?=\W|\n))`, ByGroups(Text, GenericStrong, GenericStrong, Text), nil},
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/markless.go b/vendor/github.com/alecthomas/chroma/v2/lexers/markless.go
index 508513d7..437590e9 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/markless.go
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/markless.go
@@ -70,14 +70,14 @@ func marklessRules() Rules {
{`(! )([^ ]+)(.+?)$`, ByGroups(Keyword, NameFunction, NameVariable), nil},
},
"embed": {
- {`(\[ )([^ ]+)( )([^,]+)`, ByGroups(Keyword, NameFunction, TextWhitespace, String), Push("embed-options")},
+ {`(\[ )([^ ]+)( )([^,\]\n]+)`, ByGroups(Keyword, NameFunction, TextWhitespace, String), Push("embed-options")},
},
"embed-options": {
{`\\.`, Text, nil},
{`,`, Punctuation, nil},
{`\]?$`, Keyword, Pop(1)},
// Generic key or key/value pair
- {`( *)([^, \]]+)([^,\]]+)?`, ByGroups(TextWhitespace, NameFunction, String), nil},
+ {`( *)([^, \]\n]+)([^,\]\n]+)?`, ByGroups(TextWhitespace, NameFunction, String), nil},
{`.`, Text, nil},
},
"footnote": {
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/raku.go b/vendor/github.com/alecthomas/chroma/v2/lexers/raku.go
index da354dce..38d8fe8a 100644
--- a/vendor/github.com/alecthomas/chroma/v2/lexers/raku.go
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/raku.go
@@ -6,7 +6,7 @@ import (
"strings"
"unicode/utf8"
- "github.com/dlclark/regexp2"
+ "github.com/dlclark/regexp2/v2"
. "github.com/alecthomas/chroma/v2" // nolint
)
@@ -458,8 +458,7 @@ func rakuRules() Rules {
var podRegex *regexp2.Regexp
if tokenClass == rakuPod {
podRegex = regexp2.MustCompile(
- state.NamedGroups[`ws`]+`=end`+`\s+`+regexp2.Escape(state.NamedGroups[`name`]),
- 0,
+ state.NamedGroups[`ws`] + `=end` + `\s+` + regexp2.Escape(state.NamedGroups[`name`]),
)
} else {
closingChars = []rune(strings.Repeat(string(closingChar), nChars))
@@ -478,7 +477,7 @@ func rakuRules() Rules {
match, err := podRegex.FindRunesMatchStartingAt(text, searchPos+nChars)
if err == nil {
closingChars = match.Runes()
- nextClosePos = match.Index
+ nextClosePos = match.RuneIndex
} else {
nextClosePos = -1
}
@@ -1599,8 +1598,7 @@ func quote(groups []string, state *LexerState) Iterator {
var tokenStates []string
// Set tokenStates based on adverbs
- adverbs := strings.Split(adverbsStr, ":")
- for _, adverb := range adverbs {
+ for adverb := range strings.SplitSeq(adverbsStr, ":") {
switch adverb {
case "c", "closure":
tokenStates = append(tokenStates, "Q-closure")
diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/yaml_jinja.go b/vendor/github.com/alecthomas/chroma/v2/lexers/yaml_jinja.go
new file mode 100644
index 00000000..6df1911e
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/lexers/yaml_jinja.go
@@ -0,0 +1,20 @@
+package lexers
+
+import (
+ . "github.com/alecthomas/chroma/v2" // nolint
+)
+
+// YAML+Jinja is YAML with Jinja templating embedded. Used by Ansible playbooks
+// and Salt SLS files.
+var YAMLJinja = Register(DelegatingLexer(
+ MustNewXMLLexer(embedded, "embedded/yaml.xml"),
+ MustNewXMLLexer(embedded, "embedded/django_jinja.xml").SetConfig(
+ &Config{
+ Name: "YAML+Jinja",
+ Aliases: []string{"yaml+jinja", "salt", "sls", "ansible"},
+ Filenames: []string{"*.sls"},
+ MimeTypes: []string{"text/x-yaml+jinja", "text/x-sls"},
+ DotAll: true,
+ },
+ ),
+))
diff --git a/vendor/github.com/alecthomas/chroma/v2/regexp.go b/vendor/github.com/alecthomas/chroma/v2/regexp.go
index c0e5e108..2c494061 100644
--- a/vendor/github.com/alecthomas/chroma/v2/regexp.go
+++ b/vendor/github.com/alecthomas/chroma/v2/regexp.go
@@ -3,6 +3,7 @@ package chroma
import (
"encoding/json"
"fmt"
+ "maps"
"os"
"path/filepath"
"regexp"
@@ -12,7 +13,7 @@ import (
"time"
"unicode/utf8"
- "github.com/dlclark/regexp2"
+ "github.com/dlclark/regexp2/v2"
)
// A Rule is the fundamental matching unit of the Regex lexer state machine.
@@ -70,9 +71,7 @@ func (r Rules) Clone() Rules {
// Merge creates a clone of "r" then merges "rules" into the clone.
func (r Rules) Merge(rules Rules) Rules {
out := r.Clone()
- for k, v := range rules.Clone() {
- out[k] = v
- }
+ maps.Copy(out, rules.Clone())
return out
}
@@ -177,19 +176,19 @@ type LexerState struct {
// Named Group matches.
NamedGroups map[string]string
// Custum context for mutators.
- MutatorContext map[interface{}]interface{}
+ MutatorContext map[any]any
iteratorStack []Iterator
options *TokeniseOptions
newlineAdded bool
}
// Set mutator context.
-func (l *LexerState) Set(key interface{}, value interface{}) {
+func (l *LexerState) Set(key any, value any) {
l.MutatorContext[key] = value
}
// Get mutator context.
-func (l *LexerState) Get(key interface{}) interface{} {
+func (l *LexerState) Get(key any) any {
return l.MutatorContext[key]
}
@@ -308,6 +307,7 @@ type RegexLexer struct {
rules map[string][]*CompiledRule
fetchRulesFunc func() (Rules, error)
compileOnce sync.Once
+ compileError error
}
func (r *RegexLexer) String() string {
@@ -368,7 +368,7 @@ func (r *RegexLexer) maybeCompile() (err error) {
pattern = "(?" + rule.flags + ")" + pattern
}
pattern = `\G` + pattern
- rule.Regexp, err = regexp2.Compile(pattern, 0)
+ rule.Regexp, err = regexp2.Compile(pattern)
if err != nil {
return fmt.Errorf("failed to compile rule %s.%d: %s", state, i, err)
}
@@ -446,8 +446,11 @@ func (r *RegexLexer) needRules() error {
var err error
if r.fetchRulesFunc != nil {
r.compileOnce.Do(func() {
- err = r.fetchRules()
+ r.compileError = r.fetchRules()
})
+ if r.compileError != nil {
+ return r.compileError
+ }
}
if err := r.maybeCompile(); err != nil {
return err
@@ -480,7 +483,7 @@ func (r *RegexLexer) Tokenise(options *TokeniseOptions, text string) (Iterator,
Text: []rune(text),
Stack: []string{options.State},
Rules: r.rules,
- MutatorContext: map[interface{}]interface{}{},
+ MutatorContext: map[any]any{},
}
return state.Iterator, nil
}
@@ -497,7 +500,7 @@ func (r *RegexLexer) MustRules() Rules {
func matchRules(text []rune, pos int, rules []*CompiledRule) (int, *CompiledRule, []string, map[string]string) {
for i, rule := range rules {
match, err := rule.Regexp.FindRunesMatchStartingAt(text, pos)
- if match != nil && err == nil && match.Index == pos {
+ if match != nil && err == nil && match.RuneIndex == pos {
groups := []string{}
namedGroups := make(map[string]string)
for _, g := range match.Groups() {
diff --git a/vendor/github.com/alecthomas/chroma/v2/renovate.json5 b/vendor/github.com/alecthomas/chroma/v2/renovate.json5
index 9ade4812..050483e8 100644
--- a/vendor/github.com/alecthomas/chroma/v2/renovate.json5
+++ b/vendor/github.com/alecthomas/chroma/v2/renovate.json5
@@ -9,6 +9,7 @@
"schedule:earlyMondays", // Run once a week.
'helpers:pinGitHubActionDigests',
],
+ "postUpdateOptions": ["gomodTidy"],
"packageRules": [
{
"matchPackageNames": ["golangci-lint"],
diff --git a/vendor/github.com/alecthomas/chroma/v2/serialise.go b/vendor/github.com/alecthomas/chroma/v2/serialise.go
index 3d7f6c5d..dacf69c5 100644
--- a/vendor/github.com/alecthomas/chroma/v2/serialise.go
+++ b/vendor/github.com/alecthomas/chroma/v2/serialise.go
@@ -13,7 +13,7 @@ import (
"regexp"
"strings"
- "github.com/dlclark/regexp2"
+ "github.com/dlclark/regexp2/v2"
)
// Serialisation of Chroma rules to XML. The format is:
@@ -440,14 +440,14 @@ func (t TokenType) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
}
// This hijinks is a bit unfortunate but without it we can't deserialise into TokenType.
-func newFromTemplate(template interface{}) (value func() interface{}, target interface{}) {
+func newFromTemplate(template any) (value func() any, target any) {
t := reflect.TypeOf(template)
- if t.Kind() == reflect.Ptr {
+ if t.Kind() == reflect.Pointer {
v := reflect.New(t.Elem())
return v.Interface, v.Interface()
}
v := reflect.New(t)
- return func() interface{} { return v.Elem().Interface() }, v.Interface()
+ return func() any { return v.Elem().Interface() }, v.Interface()
}
func (b *Emitters) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
diff --git a/vendor/github.com/alecthomas/chroma/v2/style.go b/vendor/github.com/alecthomas/chroma/v2/style.go
index cc8d9a60..36989ad3 100644
--- a/vendor/github.com/alecthomas/chroma/v2/style.go
+++ b/vendor/github.com/alecthomas/chroma/v2/style.go
@@ -4,7 +4,8 @@ import (
"encoding/xml"
"fmt"
"io"
- "sort"
+ "maps"
+ "slices"
"strings"
)
@@ -18,6 +19,24 @@ const (
No
)
+// Mode indicates whether a style is intended for a light or dark background.
+type Mode uint8
+
+// Mode values.
+const (
+ Light Mode = iota
+ Dark
+)
+
+func (m Mode) String() string {
+ switch m {
+ case Dark:
+ return "dark"
+ default:
+ return "light"
+ }
+}
+
func (t Trilean) String() string {
switch t {
case Yes:
@@ -31,12 +50,14 @@ func (t Trilean) String() string {
// Prefix returns s with "no" as a prefix if Trilean is no.
func (t Trilean) Prefix(s string) string {
- if t == Yes {
+ switch t {
+ case Yes:
return s
- } else if t == No {
+ case No:
return "no" + s
+ default:
+ return ""
}
- return ""
}
// A StyleEntry in the Style map.
@@ -111,11 +132,10 @@ func (s StyleEntry) Sub(e StyleEntry) StyleEntry {
// Ancestors should be provided from oldest to newest.
func (s StyleEntry) Inherit(ancestors ...StyleEntry) StyleEntry {
out := s
- for i := len(ancestors) - 1; i >= 0; i-- {
+ for _, ancestor := range slices.Backward(ancestors) {
if out.NoInherit {
return out
}
- ancestor := ancestors[i]
if !out.Colour.IsSet() {
out.Colour = ancestor.Colour
}
@@ -147,19 +167,24 @@ func (s StyleEntry) IsZero() bool {
//
// Once built, a Style is immutable.
type StyleBuilder struct {
- entries map[TokenType]string
- name string
- parent *Style
+ entries map[TokenType]string
+ name string
+ counterpart string
+ parent *Style
}
func NewStyleBuilder(name string) *StyleBuilder {
return &StyleBuilder{name: name, entries: map[TokenType]string{}}
}
+// Counterpart sets the lowercase name of the opposite-mode style.
+func (s *StyleBuilder) Counterpart(name string) *StyleBuilder {
+ s.counterpart = strings.ToLower(name)
+ return s
+}
+
func (s *StyleBuilder) AddAll(entries StyleEntries) *StyleBuilder {
- for ttype, entry := range entries {
- s.entries[ttype] = entry
- }
+ maps.Copy(s.entries, entries)
return s
}
@@ -205,10 +230,15 @@ func (s *StyleBuilder) Transform(transform func(StyleEntry) StyleEntry) *StyleBu
}
func (s *StyleBuilder) Build() (*Style, error) {
+ counterpart := s.counterpart
+ if counterpart == "" && s.parent != nil {
+ counterpart = s.parent.Counterpart
+ }
style := &Style{
- Name: s.name,
- entries: map[TokenType]StyleEntry{},
- parent: s.parent,
+ Name: s.name,
+ Counterpart: counterpart,
+ entries: map[TokenType]StyleEntry{},
+ parent: s.parent,
}
for ttype, descriptor := range s.entries {
entry, err := ParseStyleEntry(descriptor)
@@ -257,9 +287,23 @@ func MustNewStyle(name string, entries StyleEntries) *Style {
//
// See http://pygments.org/docs/styles/ for details. Semantics are intended to be identical.
type Style struct {
- Name string
- entries map[TokenType]StyleEntry
- parent *Style
+ Name string
+ // Counterpart is the lowercase name of the style intended as this style's
+ // opposite-mode pair (eg. "github-dark" for "github"). Resolved via
+ // styles.GetForMode. May be empty.
+ Counterpart string
+ entries map[TokenType]StyleEntry
+ parent *Style
+}
+
+// Mode returns Light or Dark based on the brightness of the Background entry's
+// background colour. Styles with an unset Background default to Light.
+func (s *Style) Mode() Mode {
+ bg := s.get(Background).Background
+ if bg.IsSet() && bg.Brightness() < 0.5 {
+ return Dark
+ }
+ return Light
}
func (s *Style) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
@@ -268,6 +312,9 @@ func (s *Style) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
}
start.Name = xml.Name{Local: "style"}
start.Attr = []xml.Attr{{Name: xml.Name{Local: "name"}, Value: s.Name}}
+ if s.Counterpart != "" {
+ start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: "counterpart"}, Value: s.Counterpart})
+ }
if err := e.EncodeToken(start); err != nil {
return err
}
@@ -275,7 +322,7 @@ func (s *Style) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
for ttype := range s.entries {
sorted = append(sorted, ttype)
}
- sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })
+ slices.Sort(sorted)
for _, ttype := range sorted {
entry := s.entries[ttype]
el := xml.StartElement{Name: xml.Name{Local: "entry"}}
@@ -295,9 +342,12 @@ func (s *Style) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
func (s *Style) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
- if attr.Name.Local == "name" {
+ switch attr.Name.Local {
+ case "name":
s.Name = attr.Value
- } else {
+ case "counterpart":
+ s.Counterpart = strings.ToLower(attr.Value)
+ default:
return fmt.Errorf("unexpected attribute %s", attr.Name.Local)
}
}
@@ -437,8 +487,7 @@ func MustParseStyleEntry(entry string) StyleEntry {
// ParseStyleEntry parses a Pygments style entry.
func ParseStyleEntry(entry string) (StyleEntry, error) { // nolint: gocyclo
out := StyleEntry{}
- parts := strings.Fields(entry)
- for _, part := range parts {
+ for part := range strings.FieldsSeq(entry) {
switch {
case part == "italic":
out.Italic = Yes
diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/api.go b/vendor/github.com/alecthomas/chroma/v2/styles/api.go
index e26d6f0a..43fa26dd 100644
--- a/vendor/github.com/alecthomas/chroma/v2/styles/api.go
+++ b/vendor/github.com/alecthomas/chroma/v2/styles/api.go
@@ -4,6 +4,7 @@ import (
"embed"
"io/fs"
"sort"
+ "strings"
"github.com/alecthomas/chroma/v2"
)
@@ -31,7 +32,7 @@ var Registry = func() map[string]*chroma.Style {
if err != nil {
panic(err)
}
- registry[style.Name] = style
+ registry[strings.ToLower(style.Name)] = style
_ = r.Close()
}
return registry
@@ -42,7 +43,7 @@ var Fallback = Registry["swapoff"]
// Register a chroma.Style.
func Register(style *chroma.Style) *chroma.Style {
- Registry[style.Name] = style
+ Registry[strings.ToLower(style.Name)] = style
return style
}
@@ -58,8 +59,37 @@ func Names() []string {
// Get named style, or Fallback.
func Get(name string) *chroma.Style {
- if style, ok := Registry[name]; ok {
+ if style, ok := Registry[strings.ToLower(name)]; ok {
return style
}
return Fallback
}
+
+// GetForMode returns the named style if it already matches mode, otherwise its
+// registered counterpart if one exists and matches mode. If neither matches,
+// the originally-requested style is returned (or Fallback if the name is
+// unknown), so callers always get something usable.
+func GetForMode(name string, mode chroma.Mode) *chroma.Style {
+ style := Get(name)
+ if style.Mode() == mode {
+ return style
+ }
+ if style.Counterpart == "" {
+ return style
+ }
+ counterpart, ok := Registry[style.Counterpart]
+ if !ok || counterpart.Mode() != mode {
+ return style
+ }
+ return counterpart
+}
+
+// RegisterPair links two styles as light/dark counterparts of each other.
+//
+// Both styles are also registered if they are not already present.
+func RegisterPair(a, b *chroma.Style) {
+ Register(a)
+ Register(b)
+ a.Counterpart = strings.ToLower(b.Name)
+ b.Counterpart = strings.ToLower(a.Name)
+}
diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml
index c87c8765..a6e41ab8 100644
--- a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml
@@ -1,4 +1,4 @@
-
\ No newline at end of file
diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml b/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml
index 711aeafc..9f2b7e14 100644
--- a/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml
@@ -1,4 +1,4 @@
-
diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml b/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml
new file mode 100644
index 00000000..622ae4e4
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml
@@ -0,0 +1,83 @@
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml b/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml
new file mode 100644
index 00000000..bc9b6461
--- /dev/null
+++ b/vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml
@@ -0,0 +1,83 @@
+
diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml b/vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml
index 023137aa..066efa7c 100644
--- a/vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml
+++ b/vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml
@@ -1,4 +1,4 @@
-
`)
diff --git a/vendor/github.com/golangci/dupl/suffixtree/dupl.go b/vendor/github.com/golangci/dupl/suffixtree/dupl.go
index ab145b4f..0263203e 100644
--- a/vendor/github.com/golangci/dupl/suffixtree/dupl.go
+++ b/vendor/github.com/golangci/dupl/suffixtree/dupl.go
@@ -54,7 +54,7 @@ func (c *contextList) append(c2 *contextList) {
}
}
-// FindDuplOver find pairs of maximal duplicities over a threshold
+// FindDuplOver finds pairs of maximal duplicities over a threshold
// length.
func (t *STree) FindDuplOver(threshold int) <-chan Match {
auxTran := newTran(0, 0, t.root)
diff --git a/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go b/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go
index 871469e8..30aaa6f4 100644
--- a/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go
+++ b/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go
@@ -38,7 +38,7 @@ func New() *STree {
return t
}
-// Update refreshes the suffix tree to by new data.
+// Update refreshes the suffix tree with new data.
func (t *STree) Update(data ...Token) {
t.data = append(t.data, data...)
for range data {
@@ -79,8 +79,8 @@ func (t *STree) update() {
}
// testAndSplit tests whether a state with canonical ref. pair
-// (s, (start, end)) is the end point, that is, a state that have
-// a c-transition. If not, then state (exs, (start, end)) is made
+// (s, (start, end)) is the end point, that is, a state that has
+// a c-transition. If not, then the state (exs, (start, end)) is made
// explicit (if not already so).
func (t *STree) testAndSplit(s *state, start, end Pos) (exs *state, endPoint bool) {
c := t.data[t.end]
@@ -148,11 +148,11 @@ func (t *STree) String() string {
return buf.String()
}
-func printState(buf *bytes.Buffer, s *state, ident int) {
+func printState(buf *bytes.Buffer, s *state, indent int) {
for _, tr := range s.trans {
- fmt.Fprint(buf, strings.Repeat(" ", ident))
+ fmt.Fprint(buf, strings.Repeat(" ", indent))
fmt.Fprintf(buf, "* (%d, %d)\n", tr.start, tr.ActEnd())
- printState(buf, tr.state, ident+1)
+ printState(buf, tr.state, indent+1)
}
}
diff --git a/vendor/github.com/golangci/dupl/syntax/golang/golang.go b/vendor/github.com/golangci/dupl/syntax/golang/golang.go
index a0b1e77e..ff3e51b2 100644
--- a/vendor/github.com/golangci/dupl/syntax/golang/golang.go
+++ b/vendor/github.com/golangci/dupl/syntax/golang/golang.go
@@ -39,6 +39,7 @@ const (
IfStmt
IncDecStmt
IndexExpr
+ IndexListExpr
InterfaceType
KeyValueExpr
LabeledStmt
@@ -234,6 +235,9 @@ func (t *transformer) trans(node ast.Node) (o *syntax.Node) {
case *ast.FuncType:
o.Type = FuncType
+ if n.TypeParams != nil {
+ o.AddChildren(t.trans(n.TypeParams))
+ }
o.AddChildren(t.trans(n.Params))
if n.Results != nil {
o.AddChildren(t.trans(n.Results))
@@ -270,6 +274,13 @@ func (t *transformer) trans(node ast.Node) (o *syntax.Node) {
o.Type = IndexExpr
o.AddChildren(t.trans(n.X), t.trans(n.Index))
+ case *ast.IndexListExpr:
+ o.Type = IndexListExpr
+ o.AddChildren(t.trans(n.X))
+ for _, idx := range n.Indices {
+ o.AddChildren(t.trans(idx))
+ }
+
case *ast.InterfaceType:
o.Type = InterfaceType
o.AddChildren(t.trans(n.Methods))
@@ -358,7 +369,11 @@ func (t *transformer) trans(node ast.Node) (o *syntax.Node) {
case *ast.TypeSpec:
o.Type = TypeSpec
- o.AddChildren(t.trans(n.Name), t.trans(n.Type))
+ o.AddChildren(t.trans(n.Name))
+ if n.TypeParams != nil {
+ o.AddChildren(t.trans(n.TypeParams))
+ }
+ o.AddChildren(t.trans(n.Type))
case *ast.TypeSwitchStmt:
o.Type = TypeSwitchStmt
diff --git a/vendor/github.com/golangci/dupl/syntax/syntax.go b/vendor/github.com/golangci/dupl/syntax/syntax.go
index 9b11d311..871f6718 100644
--- a/vendor/github.com/golangci/dupl/syntax/syntax.go
+++ b/vendor/github.com/golangci/dupl/syntax/syntax.go
@@ -129,8 +129,8 @@ func getUnitsIndexes(nodeSeq []*Node, threshold int) []int {
return indexes
}
-// isCyclic finds out whether there is a repetive pattern in the found clone. If positive,
-// it return false to point out that the clone would be redundant.
+// isCyclic finds out whether there is a repetitive pattern in the found clone. If positive,
+// it returns true to point out that the clone would be redundant.
func isCyclic(indexes []int, nodes []*Node) bool {
cnt := len(indexes)
if cnt <= 1 {
diff --git a/vendor/github.com/golangci/gofmt/Makefile b/vendor/github.com/golangci/gofmt/Makefile
new file mode 100644
index 00000000..8375bf40
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/Makefile
@@ -0,0 +1,9 @@
+.PHONY: build
+
+default: test build
+
+build:
+ go build .
+
+test:
+ go test ./...
diff --git a/vendor/github.com/golangci/gofmt/gofmt.go b/vendor/github.com/golangci/gofmt/gofmt.go
new file mode 100644
index 00000000..430a1b8d
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/gofmt.go
@@ -0,0 +1,73 @@
+package gofmt
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/printer"
+ "go/token"
+
+ "github.com/golangci/gofmt/internal"
+)
+
+type Options struct {
+ NeedSimplify bool
+ RewriteRules []RewriteRule
+}
+
+type RewriteRule struct {
+ Pattern string
+ Replacement string
+}
+
+// Source formats the code like gofmt.
+// Empty string `rewrite` will be ignored.
+// https://github.com/golang/go/blob/1b291b70dff51732415da5b68debe323704d8e8d/src/cmd/gofmt/gofmt.go#L236-L300
+// https://github.com/golang/go/blob/1b291b70dff51732415da5b68debe323704d8e8d/src/go/format/format.go#L101-L115
+func Source(filename string, src []byte, opts Options) ([]byte, error) {
+ fset := token.NewFileSet()
+
+ file, sourceAdj, indentAdj, err := internal.Parse(fset, filename, src, false)
+ if err != nil {
+ return nil, err
+ }
+
+ file, err = rewriteFileContent(fset, file, opts.RewriteRules)
+ if err != nil {
+ return nil, err
+ }
+
+ ast.SortImports(fset, file)
+
+ if opts.NeedSimplify {
+ internal.Simplify(file)
+ }
+
+ return internal.Format(fset, file, sourceAdj, indentAdj, src, printer.Config{Mode: internal.PrinterMode, Tabwidth: internal.TabWidth})
+}
+
+func rewriteFileContent(fset *token.FileSet, file *ast.File, rewriteRules []RewriteRule) (*ast.File, error) {
+ for _, rewriteRule := range rewriteRules {
+ pattern, err := parseExpression(rewriteRule.Pattern, "pattern")
+ if err != nil {
+ return nil, err
+ }
+
+ replacement, err := parseExpression(rewriteRule.Replacement, "replacement")
+ if err != nil {
+ return nil, err
+ }
+
+ file = internal.RewriteFile(fset, pattern, replacement, file)
+ }
+
+ return file, nil
+}
+
+func parseExpression(s, what string) (ast.Expr, error) {
+ x, err := parser.ParseExpr(s)
+ if err != nil {
+ return nil, fmt.Errorf("parsing %s %q at %s\n", what, s, err)
+ }
+ return x, nil
+}
diff --git a/vendor/github.com/golangci/gofmt/gofmt/golangci.go b/vendor/github.com/golangci/gofmt/gofmt/golangci.go
deleted file mode 100644
index a7f3ef6e..00000000
--- a/vendor/github.com/golangci/gofmt/gofmt/golangci.go
+++ /dev/null
@@ -1,133 +0,0 @@
-package gofmt
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/parser"
- "go/printer"
- "go/token"
- "os"
- "path/filepath"
- "sync"
-
- "github.com/rogpeppe/go-internal/diff"
-)
-
-type Options struct {
- NeedSimplify bool
- RewriteRules []RewriteRule
-}
-
-var parserModeMu sync.RWMutex
-
-type RewriteRule struct {
- Pattern string
- Replacement string
-}
-
-// Run runs gofmt.
-// Deprecated: use [Source] instead.
-func Run(filename string, needSimplify bool) ([]byte, error) {
- return RunRewrite(filename, needSimplify, nil)
-}
-
-// RunRewrite runs gofmt.
-// Deprecated: use [Source] instead.
-func RunRewrite(filename string, needSimplify bool, rewriteRules []RewriteRule) ([]byte, error) {
- src, err := os.ReadFile(filename)
- if err != nil {
- return nil, err
- }
-
- fset := token.NewFileSet()
-
- parserModeMu.Lock()
- initParserMode()
- parserModeMu.Unlock()
-
- file, sourceAdj, indentAdj, err := parse(fset, filename, src, false)
- if err != nil {
- return nil, err
- }
-
- file, err = rewriteFileContent(fset, file, rewriteRules)
- if err != nil {
- return nil, err
- }
-
- ast.SortImports(fset, file)
-
- if needSimplify {
- simplify(file)
- }
-
- res, err := format(fset, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth})
- if err != nil {
- return nil, err
- }
-
- if bytes.Equal(src, res) {
- return nil, nil
- }
-
- // formatting has changed
- newName := filepath.ToSlash(filename)
- oldName := newName + ".orig"
-
- return diff.Diff(oldName, src, newName, res), nil
-}
-
-// Source formats the code like gofmt.
-// Empty string `rewrite` will be ignored.
-func Source(filename string, src []byte, opts Options) ([]byte, error) {
- fset := token.NewFileSet()
-
- parserModeMu.Lock()
- initParserMode()
- parserModeMu.Unlock()
-
- file, sourceAdj, indentAdj, err := parse(fset, filename, src, false)
- if err != nil {
- return nil, err
- }
-
- file, err = rewriteFileContent(fset, file, opts.RewriteRules)
- if err != nil {
- return nil, err
- }
-
- ast.SortImports(fset, file)
-
- if opts.NeedSimplify {
- simplify(file)
- }
-
- return format(fset, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth})
-}
-
-func rewriteFileContent(fset *token.FileSet, file *ast.File, rewriteRules []RewriteRule) (*ast.File, error) {
- for _, rewriteRule := range rewriteRules {
- pattern, err := parseExpression(rewriteRule.Pattern, "pattern")
- if err != nil {
- return nil, err
- }
-
- replacement, err := parseExpression(rewriteRule.Replacement, "replacement")
- if err != nil {
- return nil, err
- }
-
- file = rewriteFile(fset, pattern, replacement, file)
- }
-
- return file, nil
-}
-
-func parseExpression(s, what string) (ast.Expr, error) {
- x, err := parser.ParseExpr(s)
- if err != nil {
- return nil, fmt.Errorf("parsing %s %q at %s\n", what, s, err)
- }
- return x, nil
-}
diff --git a/vendor/github.com/golangci/gofmt/gofmt/readme.md b/vendor/github.com/golangci/gofmt/gofmt/readme.md
deleted file mode 100644
index d11d4641..00000000
--- a/vendor/github.com/golangci/gofmt/gofmt/readme.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Hard Fork of gofmt
-
-- https://github.com/golang/go/blob/master/src/cmd/gofmt/
-- https://github.com/golang/go/blob/master/src/internal/cfg
-- https://github.com/golang/go/blob/master/src/internal/goarch
-- https://github.com/golang/go/blob/master/src/internal/testenv
-- https://github.com/golang/go/blob/master/src/internal/platform
-- https://github.com/golang/go/blob/master/src/internal/diff -> replaced by `github.com/rogpeppe/go-internal/diff`
-
-## Updates
-
-- 2025-07-04: Sync with go1.24.4
-- 2025-04-14: Sync with go1.23.8
-- 2024-08-17: Sync with go1.22.6
-- 2023-02-28: Sync with go1.21.7
-- 2023-10-04: Sync with go1.20.8
-- 2023-10-04: Sync with go1.19.13
-- 2022-08-31: Sync with go1.18.5
diff --git a/vendor/github.com/golangci/gofmt/internal/.gitattributes b/vendor/github.com/golangci/gofmt/internal/.gitattributes
new file mode 100644
index 00000000..19d80d28
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/internal/.gitattributes
@@ -0,0 +1 @@
+/testdata/crlf.input text eol=crlf
diff --git a/vendor/github.com/golangci/gofmt/gofmt/LICENSE b/vendor/github.com/golangci/gofmt/internal/LICENSE
similarity index 100%
rename from vendor/github.com/golangci/gofmt/gofmt/LICENSE
rename to vendor/github.com/golangci/gofmt/internal/LICENSE
diff --git a/vendor/github.com/golangci/gofmt/gofmt/doc.go b/vendor/github.com/golangci/gofmt/internal/doc.go
similarity index 99%
rename from vendor/github.com/golangci/gofmt/gofmt/doc.go
rename to vendor/github.com/golangci/gofmt/internal/doc.go
index d0a45802..6a25f1de 100644
--- a/vendor/github.com/golangci/gofmt/gofmt/doc.go
+++ b/vendor/github.com/golangci/gofmt/internal/doc.go
@@ -99,7 +99,7 @@ When invoked with -s gofmt will make the following source transformations where
This may result in changes that are incompatible with earlier versions of Go.
*/
-package gofmt
+package internal
// BUG(rsc): The implementation of -r is a bit slow.
// BUG(gri): If -w fails, the restored original file may not have some of the
diff --git a/vendor/github.com/golangci/gofmt/gofmt/gofmt.go b/vendor/github.com/golangci/gofmt/internal/gofmt.go
similarity index 89%
rename from vendor/github.com/golangci/gofmt/gofmt/gofmt.go
rename to vendor/github.com/golangci/gofmt/internal/gofmt.go
index f4543582..1fd62b8f 100644
--- a/vendor/github.com/golangci/gofmt/gofmt/gofmt.go
+++ b/vendor/github.com/golangci/gofmt/internal/gofmt.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package gofmt
+package internal
import (
"bytes"
@@ -10,7 +10,6 @@ import (
"flag"
"fmt"
"go/ast"
- "go/parser"
"go/printer"
"go/scanner"
"go/token"
@@ -39,6 +38,9 @@ var (
// debugging
cpuprofile = flag.String("gofmt.cpuprofile", "", "write cpu profile to this file")
+
+ // errors
+ errFormattingDiffers = fmt.Errorf("formatting differs from gofmt's")
)
// Keep these in sync with go/format/format.go.
@@ -64,8 +66,8 @@ const (
var fdSem = make(chan bool, 200)
var (
- rewrite func(*token.FileSet, *ast.File) *ast.File
- parserMode parser.Mode
+ rewrite func(*token.FileSet, *ast.File) *ast.File
+ // parserMode parser.Mode // NOTE(golangci-lint): replaced with a constant
)
func usage() {
@@ -73,22 +75,23 @@ func usage() {
flag.PrintDefaults()
}
+// NOTE(golangci-lint): replaced with a constant
func initParserMode() {
- parserMode = parser.ParseComments
- if *allErrors {
- parserMode |= parser.AllErrors
- }
- // It's only -r that makes use of go/ast's object resolution,
- // so avoid the unnecessary work if the flag isn't used.
- if *rewriteRule == "" {
- parserMode |= parser.SkipObjectResolution
- }
+ /*
+ parserMode = parser.ParseComments
+ if *allErrors {
+ parserMode |= parser.AllErrors
+ }
+ // It's only -r that makes use of go/ast's object resolution,
+ // so avoid the unnecessary work if the flag isn't used.
+ if *rewriteRule == "" {
+ parserMode |= parser.SkipObjectResolution
+ }
+ */
}
-func isGoFile(f fs.DirEntry) bool {
- // ignore non-Go files
- name := f.Name()
- return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") && !f.IsDir()
+func isGoFilename(name string) bool {
+ return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
}
// A sequencer performs concurrent tasks that may write output, but emits that
@@ -218,8 +221,12 @@ func (r *reporter) Report(err error) {
panic("Report with nil error")
}
st := r.getState()
- scanner.PrintError(st.err, err)
- st.exitCode = 2
+ if err == errFormattingDiffers {
+ st.exitCode = 1
+ } else {
+ scanner.PrintError(st.err, err)
+ st.exitCode = 2
+ }
}
func (r *reporter) ExitCode() int {
@@ -273,7 +280,7 @@ func processFile(filename string, info fs.FileInfo, in io.Reader, r *reporter) e
}
perm := info.Mode().Perm()
- if err := writeFile(filename, src, res, perm, info.Size()); err != nil {
+ if err := writeFile(filename, src, res, perm); err != nil {
return err
}
}
@@ -281,6 +288,7 @@ func processFile(filename string, info fs.FileInfo, in io.Reader, r *reporter) e
newName := filepath.ToSlash(filename)
oldName := newName + ".orig"
r.Write(diff.Diff(oldName, src, newName, res))
+ return errFormattingDiffers
}
}
@@ -406,34 +414,30 @@ func gofmtMain(s *sequencer) {
}
for _, arg := range args {
- switch info, err := os.Stat(arg); {
- case err != nil:
- s.AddReport(err)
- case !info.IsDir():
- // Non-directory arguments are always formatted.
- arg := arg
- s.Add(fileWeight(arg, info), func(r *reporter) error {
- return processFile(arg, info, nil, r)
- })
- default:
- // Directories are walked, ignoring non-Go files.
- err := filepath.WalkDir(arg, func(path string, f fs.DirEntry, err error) error {
- if err != nil || !isGoFile(f) {
- return err
- }
- info, err := f.Info()
- if err != nil {
- s.AddReport(err)
- return nil
- }
- s.Add(fileWeight(path, info), func(r *reporter) error {
- return processFile(path, info, nil, r)
- })
- return nil
- })
+ // Walk each given argument as a directory tree.
+ // If the argument is not a directory, it's always formatted as a Go file.
+ // If the argument is a directory, we walk it, ignoring non-Go files.
+ if err := filepath.WalkDir(arg, func(path string, d fs.DirEntry, err error) error {
+ switch {
+ case err != nil:
+ return err
+ case d.IsDir():
+ return nil // simply recurse into directories
+ case path == arg:
+ // non-directories given as explicit arguments are always formatted
+ case !isGoFilename(d.Name()):
+ return nil // skip walked non-Go files
+ }
+ info, err := d.Info()
if err != nil {
- s.AddReport(err)
+ return err
}
+ s.Add(fileWeight(path, info), func(r *reporter) error {
+ return processFile(path, info, nil, r)
+ })
+ return nil
+ }); err != nil {
+ s.AddReport(err)
}
}
}
@@ -458,7 +462,7 @@ func fileWeight(path string, info fs.FileInfo) int64 {
}
// writeFile updates a file with the new formatted data.
-func writeFile(filename string, orig, formatted []byte, perm fs.FileMode, size int64) error {
+func writeFile(filename string, orig, formatted []byte, perm fs.FileMode) error {
// Make a temporary backup file before rewriting the original file.
bakname, err := backupFile(filename, orig, perm)
if err != nil {
@@ -482,7 +486,7 @@ func writeFile(filename string, orig, formatted []byte, perm fs.FileMode, size i
}
n, err := fout.Write(formatted)
- if err == nil && int64(n) < size {
+ if err == nil {
err = fout.Truncate(int64(n))
}
diff --git a/vendor/github.com/golangci/gofmt/internal/golangci.go b/vendor/github.com/golangci/gofmt/internal/golangci.go
new file mode 100644
index 00000000..b05e5aaf
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/internal/golangci.go
@@ -0,0 +1,51 @@
+package internal
+
+import (
+ "go/ast"
+ "go/parser"
+ "go/printer"
+ "go/token"
+)
+
+/*
+ The goal of this file is:
+ - to expose the unexported constants and the function.
+ - set the parserMode.
+*/
+
+const (
+ TabWidth = tabWidth
+ PrinterMode = printerMode
+)
+
+// https://github.com/golang/go/blob/1b291b70dff51732415da5b68debe323704d8e8d/src/cmd/gofmt/gofmt.go#L81-L91
+// https://github.com/golang/go/blob/1b291b70dff51732415da5b68debe323704d8e8d/src/go/format/format.go#L41
+const parserMode = parser.ParseComments | parser.SkipObjectResolution
+
+func Parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
+ file *ast.File,
+ sourceAdj func(src []byte, indent int) []byte,
+ indentAdj int,
+ err error,
+) {
+ return parse(fset, filename, src, fragmentOk)
+}
+
+func Format(
+ fset *token.FileSet,
+ file *ast.File,
+ sourceAdj func(src []byte, indent int) []byte,
+ indentAdj int,
+ src []byte,
+ cfg printer.Config,
+) ([]byte, error) {
+ return format(fset, file, sourceAdj, indentAdj, src, cfg)
+}
+
+func Simplify(f *ast.File) {
+ simplify(f)
+}
+
+func RewriteFile(fileSet *token.FileSet, pattern, replace ast.Expr, p *ast.File) *ast.File {
+ return rewriteFile(fileSet, pattern, replace, p)
+}
diff --git a/vendor/github.com/golangci/gofmt/gofmt/internal.go b/vendor/github.com/golangci/gofmt/internal/internal.go
similarity index 96%
rename from vendor/github.com/golangci/gofmt/gofmt/internal.go
rename to vendor/github.com/golangci/gofmt/internal/internal.go
index 231a2509..ef60a143 100644
--- a/vendor/github.com/golangci/gofmt/gofmt/internal.go
+++ b/vendor/github.com/golangci/gofmt/internal/internal.go
@@ -7,7 +7,7 @@
// one without the other. Determine if we can factor out functionality
// in a public API. See also #11844 for context.
-package gofmt
+package internal
import (
"bytes"
@@ -26,13 +26,6 @@ func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
indentAdj int,
err error,
) {
-
- // START - Change related to usage inside golangci-lint
- parserModeMu.Lock()
- parserMode := parserMode
- parserModeMu.Unlock()
- // END - Change related to usage inside golangci-lint
-
// Try as whole source file.
file, err = parser.ParseFile(fset, filename, src, parserMode)
// If there's no error, return. If the error is that the source file didn't begin with a
diff --git a/vendor/github.com/golangci/gofmt/gofmt/rewrite.go b/vendor/github.com/golangci/gofmt/internal/rewrite.go
similarity index 96%
rename from vendor/github.com/golangci/gofmt/gofmt/rewrite.go
rename to vendor/github.com/golangci/gofmt/internal/rewrite.go
index c95d44f6..0a399986 100644
--- a/vendor/github.com/golangci/gofmt/gofmt/rewrite.go
+++ b/vendor/github.com/golangci/gofmt/internal/rewrite.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package gofmt
+package internal
import (
"fmt"
@@ -105,11 +105,11 @@ var (
objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
scopePtrNil = reflect.ValueOf((*ast.Scope)(nil))
- identType = reflect.TypeOf((*ast.Ident)(nil))
- objectPtrType = reflect.TypeOf((*ast.Object)(nil))
- positionType = reflect.TypeOf(token.NoPos)
- callExprType = reflect.TypeOf((*ast.CallExpr)(nil))
- scopePtrType = reflect.TypeOf((*ast.Scope)(nil))
+ identType = reflect.TypeFor[*ast.Ident]()
+ objectPtrType = reflect.TypeFor[*ast.Object]()
+ positionType = reflect.TypeFor[token.Pos]()
+ callExprType = reflect.TypeFor[*ast.CallExpr]()
+ scopePtrType = reflect.TypeFor[*ast.Scope]()
)
// apply replaces each AST field x in val with f(x), returning val.
diff --git a/vendor/github.com/golangci/gofmt/gofmt/simplify.go b/vendor/github.com/golangci/gofmt/internal/simplify.go
similarity index 99%
rename from vendor/github.com/golangci/gofmt/gofmt/simplify.go
rename to vendor/github.com/golangci/gofmt/internal/simplify.go
index 3b34d562..d57e8cef 100644
--- a/vendor/github.com/golangci/gofmt/gofmt/simplify.go
+++ b/vendor/github.com/golangci/gofmt/internal/simplify.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package gofmt
+package internal
import (
"go/ast"
diff --git a/vendor/github.com/golangci/gofmt/readme.md b/vendor/github.com/golangci/gofmt/readme.md
new file mode 100644
index 00000000..6e1b0036
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/readme.md
@@ -0,0 +1,46 @@
+# Hard Fork of gofmt
+
+## Updates
+
+- 2026-08-20: Sync with go1.27.0
+- 2025-12-14: Sync with go1.26.0-pre-rc1
+ - except (because it uses go1.26 specific elements):
+ - `internal/testenv/testenv_unix.go`
+ - `internal/platform/zosarch.go`
+- 2025-07-04: Sync with go1.24.4
+- 2025-04-14: Sync with go1.23.8
+- 2024-08-17: Sync with go1.22.6
+- 2023-02-28: Sync with go1.21.7
+- 2023-10-04: Sync with go1.20.8
+- 2023-10-04: Sync with go1.19.13
+- 2022-08-31: Sync with go1.18.5
+
+## Notes
+
+### Packages
+
+- https://github.com/golang/go/blob/master/src/cmd/gofmt/
+- https://github.com/golang/go/blob/master/src/internal/cfg
+- https://github.com/golang/go/blob/master/src/internal/goarch
+- https://github.com/golang/go/blob/master/src/internal/testenv
+- https://github.com/golang/go/blob/master/src/internal/platform
+- https://github.com/golang/go/blob/master/src/internal/diff -> replaced by `github.com/rogpeppe/go-internal/diff`
+
+### Details
+
+`go/src/cmd/gofmt/internal.go` and `go/src/go/format/internal.go` are identical.
+The `parserMode` is a global variable for `gofmt` and a constant for `go/format`.
+
+The constants (`tabWidth`, `printerMode`, `printerNormalizeNumbers`) are duplicated inside:
+- [`go/src/cmd/gofmt/gofmt.go`](https://github.com/golang/go/blob/1b291b70dff51732415da5b68debe323704d8e8d/src/cmd/gofmt/gofmt.go#L49-L59)
+- [`go/src/go/format/format.go`](https://github.com/golang/go/blob/1b291b70dff51732415da5b68debe323704d8e8d/src/go/format/format.go#L27-L37)
+
+Theoretically, only the following files are required:
+- `gofmt.go` (only the constants (`tabWidth`, `printerMode`, `printerNormalizeNumbers`))
+- `internal.go`
+- `LICENSE`
+- `rewrite.go`
+- `simplify.go`
+
+But it's easier to synchronize everything to follow changes.
+But the isolation of `internal` packages from Go can be complex, so maybe, at some point, we will reduce the number of files and so remove the `internal/internal` directory (and the test files).
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go b/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go
index 138a3614..cf20b175 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/cache/cache.go
@@ -290,7 +290,7 @@ func SetSalt(b *bytes.Buffer) {
cache.SetSalt(b.Bytes())
}
-func DefaultDir() string {
- cacheDir, _ := cache.DefaultDir()
- return cacheDir
+func DefaultDir() (string, error) {
+ cacheDir, _, err := cache.DefaultDir()
+ return cacheDir, err
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/base/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/go/base/readme.md
index 93afe9f2..49ba0c69 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/base/readme.md
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/base/readme.md
@@ -6,5 +6,7 @@ Only the function `IsETXTBSY` is extracted.
## History
+- https://github.com/golangci/golangci-lint/pull/6642
+ - sync go1.26.4 (no change)
- https://github.com/golangci/golangci-lint/pull/5576
- sync go1.24.1
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/cache.go b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/cache.go
index c514613d..1ac3f0fe 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/cache.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/cache.go
@@ -303,6 +303,10 @@ func GetBytes(c Cache, id ActionID) ([]byte, Entry, error) {
// GetMmap looks up the action ID in the cache and returns
// the corresponding output bytes.
// GetMmap should only be used for data that can be expected to fit in memory.
+// The boolean result indicates whether the file was opened.
+// If it is true, the caller should avoid attempting
+// to write to the file on Windows, because Windows locks
+// the open file, and writes to it will fail.
func GetMmap(c Cache, id ActionID) ([]byte, Entry, bool, error) {
entry, err := c.Get(id)
if err != nil {
@@ -388,13 +392,42 @@ func (c *DiskCache) Trim() error {
// trim time is too far in the future, attempt the trim anyway. It's possible that
// the cache was full when the corruption happened. Attempting a trim on
// an empty cache is cheap, so there wouldn't be a big performance hit in that case.
- if data, err := lockedfile.Read(filepath.Join(c.dir, "trim.txt")); err == nil {
+ skipTrim := func(data []byte) bool {
if t, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64); err == nil {
lastTrim := time.Unix(t, 0)
if d := now.Sub(lastTrim); d < trimInterval && d > -mtimeInterval {
- return nil
+ return true
}
}
+ return false
+ }
+ // Check to see if we need a trim. Do this check separately from the lockedfile.Transform
+ // so that we can skip getting an exclusive lock in the common case.
+ if data, err := lockedfile.Read(filepath.Join(c.dir, "trim.txt")); err == nil {
+ if skipTrim(data) {
+ return nil
+ }
+ }
+
+ errFileChanged := errors.New("file changed")
+
+ // Write the new timestamp before we start trimming to reduce the chance that multiple invocations
+ // try to trim at the same time, causing contention in CI (#76314).
+ err := lockedfile.Transform(filepath.Join(c.dir, "trim.txt"), func(data []byte) ([]byte, error) {
+ if skipTrim(data) {
+ // The timestamp in the file no longer meets the criteria for us to
+ // do a trim. It must have been updated by another go command invocation
+ // since we last read it. Skip the trim.
+ return nil, errFileChanged
+ }
+ return fmt.Appendf(nil, "%d", now.Unix()), nil
+ })
+ if errors.Is(err, errors.ErrUnsupported) {
+ return err
+ }
+ if errors.Is(err, errFileChanged) {
+ // Skip the trim because we don't need it anymore.
+ return nil
}
// Trim each of the 256 subdirectories.
@@ -406,14 +439,6 @@ func (c *DiskCache) Trim() error {
c.trimSubdir(subdir, cutoff)
}
- // Ignore errors from here: if we don't write the complete timestamp, the
- // cache will appear older than it is, and we'll trim it again next time.
- var b bytes.Buffer
- fmt.Fprintf(&b, "%d", now.Unix())
- if err := lockedfile.Write(filepath.Join(c.dir, "trim.txt"), &b, 0o666); err != nil {
- return err
- }
-
return nil
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/default.go b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/default.go
index cf38ab3d..a6cacaf1 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/default.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/default.go
@@ -29,7 +29,10 @@ const cacheREADME = `This directory holds cached build artifacts from golangci-l
// initDefaultCache does the work of finding the default cache
// the first time Default is called.
func initDefaultCache() Cache {
- dir, _ := DefaultDir()
+ dir, _, err := DefaultDir()
+ if err != nil {
+ base.Fatalf("build cache is required, but could not be located: %v", err)
+ }
if dir == "off" {
if defaultDirErr != nil {
base.Fatalf("build cache is required, but could not be located: %v", defaultDirErr)
@@ -66,16 +69,27 @@ var (
// DefaultDir returns the effective GOLANGCI_LINT_CACHE setting.
// It returns "off" if the cache is disabled,
// and reports whether the effective value differs from GOLANGCI_LINT_CACHE.
-func DefaultDir() (string, bool) {
+func DefaultDir() (string, bool, error) {
// Save the result of the first call to DefaultDir for later use in
// initDefaultCache. cmd/go/main.go explicitly sets GOLANGCI_LINT_CACHE so that
// subprocesses will inherit it, but that means initDefaultCache can't
// otherwise distinguish between an explicit "off" and a UserCacheDir error.
defaultDirOnce.Do(func() {
- defaultDir = os.Getenv(envGolangciLintCache)
- if defaultDir != "" {
- defaultDirChanged = true
+ // Compute default location.
+ dir, err := os.UserCacheDir()
+ if err != nil {
+ defaultDir = "off"
+ defaultDirErr = fmt.Errorf("%s is not defined and %v", envGolangciLintCache, err)
+ } else {
+ defaultDir = filepath.Join(dir, "golangci-lint")
+ }
+
+ newDir := os.Getenv(envGolangciLintCache)
+ if newDir != "" {
+ defaultDirErr = nil
+ defaultDirChanged = newDir != defaultDir
+ defaultDir = newDir
if filepath.IsAbs(defaultDir) || defaultDir == "off" {
return
}
@@ -83,17 +97,7 @@ func DefaultDir() (string, bool) {
defaultDirErr = fmt.Errorf("%s is not an absolute path", envGolangciLintCache)
return
}
-
- // Compute default location.
- dir, err := os.UserCacheDir()
- if err != nil {
- defaultDir = "off"
- defaultDirChanged = true
- defaultDirErr = fmt.Errorf("%s is not defined and %w", envGolangciLintCache, err)
- return
- }
- defaultDir = filepath.Join(dir, "golangci-lint")
})
- return defaultDir, defaultDirChanged
+ return defaultDir, defaultDirChanged, defaultDirErr
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/hash.go b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/hash.go
index 6a53dd88..3fa2422f 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/hash.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/hash.go
@@ -43,6 +43,9 @@ func stripExperiment(version string) string {
if i := strings.Index(version, " X:"); i >= 0 {
return version[:i]
}
+ if i := strings.Index(version, "-X:"); i >= 0 {
+ return version[:i]
+ }
return version
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/readme.md
index 66341fd4..6d33419f 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/readme.md
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cache/readme.md
@@ -3,7 +3,7 @@
Extracted from `go/src/cmd/go/internal/cache/`.
The main modifications are:
-- The errors management
+- The error management
- Some methods return error.
- Some errors are returned instead of being ignored.
- The name of the env vars:
@@ -12,6 +12,8 @@ The main modifications are:
## History
+- https://github.com/golangci/golangci-lint/pull/6642
+ - sync go1.26.4
- https://github.com/golangci/golangci-lint/pull/5576
- sync go1.24.1
- https://github.com/golangci/golangci-lint/pull/5100
@@ -30,7 +32,7 @@ The main modifications are:
## Previous History
-Based on the initial PR/commit the based in a mix between go1.12 and go1.13:
+Based on the initial PR/commit this was based in a mix between go1.12 and go1.13:
- cache.go (go1.13)
- cache_test.go (go1.12?)
- default.go (go1.12?)
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cacheprog/cacheprog.go b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cacheprog/cacheprog.go
index a2796592..9379636e 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cacheprog/cacheprog.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cacheprog/cacheprog.go
@@ -76,9 +76,6 @@ type Request struct {
ActionID []byte `json:",omitempty"` // or nil if not used
// OutputID is stored with the body for "put" requests.
- //
- // Prior to Go 1.24, when GOCACHEPROG was still an experiment, this was
- // accidentally named ObjectID. It was renamed to OutputID in Go 1.24.
OutputID []byte `json:",omitempty"` // or nil if not used
// Body is the body for "put" requests. It's sent after the JSON object
@@ -91,14 +88,6 @@ type Request struct {
// BodySize is the number of bytes of Body. If zero, the body isn't written.
BodySize int64 `json:",omitempty"`
-
- // ObjectID is the accidental spelling of OutputID that was used prior to Go
- // 1.24.
- //
- // Deprecated: use OutputID. This field is only populated temporarily for
- // backwards compatibility with Go 1.23 and earlier when
- // GOEXPERIMENT=gocacheprog is set. It will be removed in Go 1.25.
- ObjectID []byte `json:",omitempty"`
}
// Response is the JSON response from the child process to the go command.
@@ -125,7 +114,7 @@ type Response struct {
// For "get" requests.
Miss bool `json:",omitempty"` // cache miss
- OutputID []byte `json:",omitempty"` // the ObjectID stored with the body
+ OutputID []byte `json:",omitempty"` // the OutputID stored with the body
Size int64 `json:",omitempty"` // body size in bytes
Time *time.Time `json:",omitempty"` // when the object was put in the cache (optional; used for cache expiration)
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cacheprog/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cacheprog/readme.md
index 1b08c848..defb1ada 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/cacheprog/readme.md
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/cacheprog/readme.md
@@ -5,5 +5,7 @@ This is just a copy of the Go code without any changes.
## History
+- https://github.com/golangci/golangci-lint/pull/6642
+ - sync go1.26.4
- https://github.com/golangci/golangci-lint/pull/5576
- sync go1.24.1
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/mmap/mmap.go b/vendor/github.com/golangci/golangci-lint/v2/internal/go/mmap/mmap.go
index fd374df8..cd7ea80f 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/mmap/mmap.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/mmap/mmap.go
@@ -22,11 +22,30 @@ type Data struct {
}
// Mmap maps the given file into memory.
+// The boolean result indicates whether the file was opened.
+// If it is true, the caller should avoid attempting
+// to write to the file on Windows, because Windows locks
+// the open file, and writes to it will fail.
func Mmap(file string) (Data, bool, error) {
f, err := os.Open(file)
if err != nil {
return Data{}, false, err
}
data, err := mmapFile(f)
+
+ // Closing the file causes it not to count against this process's
+ // limit on open files; however, the mapping still counts against
+ // the system-wide limit, which is typically higher. Examples:
+ //
+ // macOS process (sysctl kern.maxfilesperproc): 61440
+ // macOS system (sysctl kern.maxfiles): 122880
+ // linux process (ulimit -n) 1048576
+ // linux system (/proc/sys/fs/file-max) 100000
+ if cerr := f.Close(); cerr != nil && err == nil {
+ return data, true, cerr
+ }
+
+ // The file is still considered to be in use on Windows after
+ // it's closed because of the mapping.
return data, true, err
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/mmap/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/go/mmap/readme.md
index 5cbfdeef..764c2444 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/mmap/readme.md
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/mmap/readme.md
@@ -5,6 +5,8 @@ This is just a copy of the Go code without any changes.
## History
+- https://github.com/golangci/golangci-lint/pull/6642
+ - sync go1.26.4
- https://github.com/golangci/golangci-lint/pull/5576
- sync go1.24.1
- https://github.com/golangci/golangci-lint/pull/5100
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/go/quoted/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/go/quoted/readme.md
index 97868185..45467e92 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/go/quoted/readme.md
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/go/quoted/readme.md
@@ -5,6 +5,8 @@ This is just a copy of the Go code without any changes.
## History
+- https://github.com/golangci/golangci-lint/pull/6642
+ - sync go1.26.4 (no change)
- https://github.com/golangci/golangci-lint/pull/5576
- sync go1.24.1 (no change)
- https://github.com/golangci/golangci-lint/pull/5100
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/old.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/old.go
index 4c346706..d6265c8c 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/old.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/old.go
@@ -16,10 +16,6 @@ type Diff struct {
ReplStart, ReplEnd int // offset of replacement text in B
}
-// DiffStrings returns the differences between two strings.
-// It does not respect rune boundaries.
-func DiffStrings(a, b string) []Diff { return diff(stringSeqs{a, b}) }
-
// DiffBytes returns the differences between two byte sequences.
// It does not respect rune boundaries.
func DiffBytes(a, b []byte) []Diff { return diff(bytesSeqs{a, b}) }
@@ -27,9 +23,13 @@ func DiffBytes(a, b []byte) []Diff { return diff(bytesSeqs{a, b}) }
// DiffRunes returns the differences between two rune sequences.
func DiffRunes(a, b []rune) []Diff { return diff(runesSeqs{a, b}) }
+// DiffLines returns the differences between two string sequences.
+func DiffLines(a, b []string) []Diff { return diff(linesSeqs{a, b}) }
+
+// A limit on how deeply the LCS algorithm should search. The value is just a guess.
+var maxDiffs = 100
+
func diff(seqs sequences) []Diff {
- // A limit on how deeply the LCS algorithm should search. The value is just a guess.
- const maxDiffs = 100
diff, _ := compute(seqs, twosided, maxDiffs/2)
return diff
}
@@ -378,10 +378,7 @@ func (e *editGraph) twoDone(df, db int) (int, bool) {
return 0, false // diagonals cannot overlap
}
kmin := max(-df, -db+e.delta)
- kmax := db + e.delta
- if df < kmax {
- kmax = df
- }
+ kmax := min(df, db+e.delta)
for k := kmin; k <= kmax; k += 2 {
x := e.vf.get(df, k)
u := e.vb.get(db, k-e.delta)
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/sequence.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/sequence.go
index 2d72d263..429e8c61 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/sequence.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs/sequence.go
@@ -13,63 +13,44 @@ type sequences interface {
commonSuffixLen(ai, aj, bi, bj int) int // len(commonSuffix(A[ai:aj], B[bi:bj]))
}
-type stringSeqs struct{ a, b string }
-
-func (s stringSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
-func (s stringSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
- return commonPrefixLenString(s.a[ai:aj], s.b[bi:bj])
-}
-func (s stringSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
- return commonSuffixLenString(s.a[ai:aj], s.b[bi:bj])
-}
-
// The explicit capacity in s[i:j:j] leads to more efficient code.
type bytesSeqs struct{ a, b []byte }
func (s bytesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
func (s bytesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
- return commonPrefixLenBytes(s.a[ai:aj:aj], s.b[bi:bj:bj])
+ return commonPrefixLen(s.a[ai:aj:aj], s.b[bi:bj:bj])
}
func (s bytesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
- return commonSuffixLenBytes(s.a[ai:aj:aj], s.b[bi:bj:bj])
+ return commonSuffixLen(s.a[ai:aj:aj], s.b[bi:bj:bj])
}
type runesSeqs struct{ a, b []rune }
func (s runesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
func (s runesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
- return commonPrefixLenRunes(s.a[ai:aj:aj], s.b[bi:bj:bj])
+ return commonPrefixLen(s.a[ai:aj:aj], s.b[bi:bj:bj])
}
func (s runesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
- return commonSuffixLenRunes(s.a[ai:aj:aj], s.b[bi:bj:bj])
+ return commonSuffixLen(s.a[ai:aj:aj], s.b[bi:bj:bj])
+}
+
+type linesSeqs struct{ a, b []string }
+
+func (s linesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
+func (s linesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
+ return commonPrefixLen(s.a[ai:aj], s.b[bi:bj])
+}
+func (s linesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
+ return commonSuffixLen(s.a[ai:aj], s.b[bi:bj])
}
// TODO(adonovan): optimize these functions using ideas from:
// - https://go.dev/cl/408116 common.go
// - https://go.dev/cl/421435 xor_generic.go
-// TODO(adonovan): factor using generics when available,
-// but measure performance impact.
-
-// commonPrefixLen* returns the length of the common prefix of a[ai:aj] and b[bi:bj].
-func commonPrefixLenBytes(a, b []byte) int {
- n := min(len(a), len(b))
- i := 0
- for i < n && a[i] == b[i] {
- i++
- }
- return i
-}
-func commonPrefixLenRunes(a, b []rune) int {
- n := min(len(a), len(b))
- i := 0
- for i < n && a[i] == b[i] {
- i++
- }
- return i
-}
-func commonPrefixLenString(a, b string) int {
+// commonPrefixLen returns the length of the common prefix of a[ai:aj] and b[bi:bj].
+func commonPrefixLen[T comparable](a, b []T) int {
n := min(len(a), len(b))
i := 0
for i < n && a[i] == b[i] {
@@ -78,16 +59,8 @@ func commonPrefixLenString(a, b string) int {
return i
}
-// commonSuffixLen* returns the length of the common suffix of a[ai:aj] and b[bi:bj].
-func commonSuffixLenBytes(a, b []byte) int {
- n := min(len(a), len(b))
- i := 0
- for i < n && a[len(a)-1-i] == b[len(b)-1-i] {
- i++
- }
- return i
-}
-func commonSuffixLenRunes(a, b []rune) int {
+// commonSuffixLen returns the length of the common suffix of a[ai:aj] and b[bi:bj].
+func commonSuffixLen[T comparable](a, b []T) int {
n := min(len(a), len(b))
i := 0
for i < n && a[len(a)-1-i] == b[len(b)-1-i] {
@@ -95,19 +68,3 @@ func commonSuffixLenRunes(a, b []rune) int {
}
return i
}
-func commonSuffixLenString(a, b string) int {
- n := min(len(a), len(b))
- i := 0
- for i < n && a[len(a)-1-i] == b[len(b)-1-i] {
- i++
- }
- return i
-}
-
-func min(x, y int) int {
- if x < y {
- return x
- } else {
- return y
- }
-}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/ndiff.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/ndiff.go
index 1c64d1ec..5083a7ea 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/ndiff.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/ndiff.go
@@ -6,11 +6,30 @@ package diff
import (
"bytes"
+ "strings"
"unicode/utf8"
"github.com/golangci/golangci-lint/v2/internal/x/tools/diff/lcs"
)
+// Lines computes differences between two strings. All edits are at line boundaries.
+func Lines(before, after string) []Edit {
+ beforeLines, bOffsets := splitLines(before)
+ afterLines, _ := splitLines(after)
+ diffs := lcs.DiffLines(beforeLines, afterLines)
+
+ // Convert from LCS diffs to Edits
+ res := make([]Edit, len(diffs))
+ for i, d := range diffs {
+ res[i] = Edit{
+ Start: bOffsets[d.Start],
+ End: bOffsets[d.End],
+ New: strings.Join(afterLines[d.ReplStart:d.ReplEnd], ""),
+ }
+ }
+ return res
+}
+
// Strings computes the differences between two strings.
// The resulting edits respect rune boundaries.
func Strings(before, after string) []Edit {
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/readme.md
index b28e41d9..7262b45a 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/readme.md
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/readme.md
@@ -5,6 +5,8 @@ This is just a copy of the code without any changes.
## History
+- https://github.com/golangci/golangci-lint/pull/6642
+ - sync with https://github.com/golang/tools/blob/v0.48.0/internal/diff/
- https://github.com/golangci/golangci-lint/pull/6076
- sync with https://github.com/golang/tools/blob/v0.37.0/internal/diff/
- https://github.com/golangci/golangci-lint/pull/5576
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/unified.go b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/unified.go
index 9a786dbb..8fc011e4 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/unified.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/diff/unified.go
@@ -7,6 +7,8 @@ package diff
import (
"fmt"
"log"
+ "regexp"
+ "strconv"
"strings"
)
@@ -18,7 +20,7 @@ const DefaultContextLines = 3
// The old and new labels are the names of the old and new files.
// If the strings are equal, it returns the empty string.
func Unified(oldLabel, newLabel, old, new string) string {
- edits := Strings(old, new)
+ edits := Lines(old, new)
unified, err := ToUnified(oldLabel, newLabel, old, edits, DefaultContextLines)
if err != nil {
// Can't happen: edits are consistent.
@@ -114,7 +116,7 @@ func toUnified(fromName, toName string, content string, edits []Edit, contextLin
if err != nil {
return u, err
}
- lines := splitLines(content)
+ lines, _ := splitLines(content)
var h *hunk
last := 0
toLine := 0
@@ -156,7 +158,8 @@ func toUnified(fromName, toName string, content string, edits []Edit, contextLin
last++
}
if edit.New != "" {
- for _, content := range splitLines(edit.New) {
+ v, _ := splitLines(edit.New)
+ for _, content := range v {
h.lines = append(h.lines, line{kind: opInsert, content: content})
toLine++
}
@@ -170,12 +173,24 @@ func toUnified(fromName, toName string, content string, edits []Edit, contextLin
return u, nil
}
-func splitLines(text string) []string {
- lines := strings.SplitAfter(text, "\n")
- if lines[len(lines)-1] == "" {
- lines = lines[:len(lines)-1]
+// split into lines removing a final empty line,
+// and also return the offsets of the line beginnings.
+func splitLines(text string) ([]string, []int) {
+ var lines []string
+ offsets := []int{0}
+ start := 0
+ for i, r := range text {
+ if r == '\n' {
+ lines = append(lines, text[start:i+1])
+ start = i + 1
+ offsets = append(offsets, start)
+ }
+ }
+ if start < len(text) {
+ lines = append(lines, text[start:])
+ offsets = append(offsets, len(text))
}
- return lines
+ return lines, offsets
}
func addEqualLines(h *hunk, lines []string, start, end int) int {
@@ -249,3 +264,51 @@ func (u unified) String() string {
}
return b.String()
}
+
+// ApplyUnified applies the unified diffs.
+func ApplyUnified(udiffs, bef string) (string, error) {
+ before := strings.Split(bef, "\n")
+ unif := strings.Split(udiffs, "\n")
+ var got []string
+ left := 0
+ // parse and apply the unified diffs
+ for _, l := range unif {
+ if len(l) == 0 {
+ continue // probably the last line (from Split)
+ }
+ switch l[0] {
+ case '@': // The @@ line
+ m := atregexp.FindStringSubmatch(l)
+ fromLine, err := strconv.Atoi(m[1])
+ if err != nil {
+ return "", fmt.Errorf("missing line number in %q", l)
+ }
+ // before is a slice, so0-based; fromLine is 1-based
+ for ; left < fromLine-1; left++ {
+ got = append(got, before[left])
+ }
+ case '+': // add this line
+ if strings.HasPrefix(l, "+++ ") {
+ continue
+ }
+ got = append(got, l[1:])
+ case '-': // delete this line
+ if strings.HasPrefix(l, "--- ") {
+ continue
+ }
+ left++
+ case ' ':
+ return "", fmt.Errorf("unexpected line %q", l)
+ default:
+ return "", fmt.Errorf("invalid unified diff: <<%s>>", udiffs)
+ }
+ }
+ // copy any remaining lines
+ for ; left < len(before); left++ {
+ got = append(got, before[left])
+ }
+ return strings.Join(got, "\n"), nil
+}
+
+// The first number in the @@ lines is the line number in the 'before' data
+var atregexp = regexp.MustCompile(`@@ -(\d+).* @@`)
diff --git a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/driverutil/readme.md b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/driverutil/readme.md
index 8720fb6f..1ee6259d 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/driverutil/readme.md
+++ b/vendor/github.com/golangci/golangci-lint/v2/internal/x/tools/driverutil/readme.md
@@ -7,6 +7,9 @@ Previously, it was `analysisinternal` and `analysisflags` packages.
## History
+- https://github.com/golangci/golangci-lint/pull/6642 (no changes)
+ - sync with https://github.com/golang/tools/blob/v0.48.0/internal/analysis/driverutil/readfile.go
+
- https://github.com/golangci/golangci-lint/pull/6434
- sync with https://github.com/golang/tools/blob/v0.43.0/internal/analysis/driverutil/readfile.go
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/custom-gcl.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/custom-gcl.jsonschema.json
new file mode 100644
index 00000000..71ea3e98
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/custom-gcl.jsonschema.json
@@ -0,0 +1,76 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$ref": "#/$defs/Configuration",
+ "$defs": {
+ "Configuration": {
+ "properties": {
+ "version": {
+ "type": "string",
+ "description": "golangci-lint version."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the binary."
+ },
+ "destination": {
+ "type": "string",
+ "description": "Destination is the path to a directory to store the binary."
+ },
+ "plugins": {
+ "items": {
+ "$ref": "#/$defs/Plugin"
+ },
+ "type": "array",
+ "description": "Plugins information."
+ }
+ },
+ "additionalProperties": false,
+ "type": "object",
+ "required": [
+ "version"
+ ],
+ "description": "Configuration represents the configuration file."
+ },
+ "Plugin": {
+ "oneOf": [
+ {
+ "required": [
+ "version"
+ ],
+ "title": "version"
+ },
+ {
+ "required": [
+ "path"
+ ],
+ "title": "path"
+ }
+ ],
+ "properties": {
+ "module": {
+ "type": "string",
+ "description": "Module name."
+ },
+ "import": {
+ "type": "string",
+ "description": "Import to use."
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the module.\nOnly for module available through a Go proxy."
+ },
+ "path": {
+ "type": "string",
+ "description": "Path to the local module.\nOnly for local module."
+ }
+ },
+ "additionalProperties": false,
+ "type": "object",
+ "required": [
+ "module"
+ ],
+ "description": "Plugin represents information about a plugin."
+ }
+ },
+ "description": "mygcl configuration definition file"
+}
\ No newline at end of file
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.jsonschema.json
new file mode 100644
index 00000000..bb4f0398
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.jsonschema.json
@@ -0,0 +1,5575 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G116",
+ "G117",
+ "G118",
+ "G119",
+ "G120",
+ "G121",
+ "G122",
+ "G123",
+ "G124",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G408",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602",
+ "G701",
+ "G702",
+ "G703",
+ "G704",
+ "G705",
+ "G706",
+ "G707",
+ "G708",
+ "G709",
+ "G710"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "inline",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-naming",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported",
+ "unusedmethod"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "atomictypes",
+ "embedlit",
+ "errorsastype",
+ "forvar",
+ "importcomment",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypeassert",
+ "reflecttypefor",
+ "slicesbackward",
+ "slicesclip",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroupgo"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "after-block",
+ "after-decl",
+ "after-defer",
+ "after-expr",
+ "after-go",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "assign",
+ "branch",
+ "cuddle-group",
+ "decl",
+ "defer",
+ "err",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "leading-whitespace",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "trailing-whitespace",
+ "type-switch"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "clickhouselint",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exhaustruct_v5",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "gomodguard_v2",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "skip-raw-strings": {
+ "description": "Skip raw string literals (backtick-delimited) from duplicate word checking.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bodycloseSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-consumption": {
+ "description": "Check that the response body is consumed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructv5Settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enforce-patterns": {
+ "description": "List of regular expressions to match type names that should be checked.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-patterns":{
+ "description": "List of regular expressions to match type names that should be skipped from checking.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "optional-patterns": {
+ "description": "List of regular expressions to match type names where all fields are treated as optional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty":{
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-patterns": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-mode":{
+ "description": "When true, only types marked with //exhaustruct:enforce directive or matching enforce-rx patterns are checked.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-loops": {
+ "description": "Disable detection of fat contexts in function literals.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-function-literals": {
+ "description": "Disable detection of fat contexts in function literals.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ },
+ "function": {
+ "description": "Checks that exported functions are placed before unexported functions.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "exclude-types": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Assignment",
+ "Binary",
+ "Case",
+ "Return",
+ "Call",
+ "CompositeLit"
+ ]
+ }
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-tests": {
+ "description": "Ignore strings from test files",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-functions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-map-keys": {
+ "description": "Ignore string literals used as map keys",
+ "type": "boolean"
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ },
+ "extra": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "group-params": {
+ "type": "boolean",
+ "default": false
+ },
+ "clothe-returns": {
+ "type": "boolean",
+ "default": false
+ },
+ "balance-calls": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "replace-allow-all": {
+ "description": "Allow all `replace` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardv2Settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-replace-directives": {
+ "type": "boolean"
+ },
+ "allowed": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "enum": ["", "exact", "prefix", "regex"],
+ "default": "exact"
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "type": "string"
+ },
+ "reason": {
+ "type": "string"
+ },
+ "recommendations": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "unusedmethod": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-unused-named-returns": {
+ "description": "Allow named returns in the signature but report them if referenced in the body or used by a naked return.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-cleanup": {
+ "description": "Check that defer is not used with t.Parallel (use t.Cleanup instead).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-global": {
+ "description": "Report the use of global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "context": {
+ "description": "Report the use of functions without a context.Context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Report dynamic log messages, such as those that are built with fmt.Sprintf.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Report log messages that do not match a particular style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Report the use of both key-value pairs and attributes within a single function call.",
+ "type": "boolean",
+ "default": true
+ },
+ "kv-only": {
+ "description": "Report any use of attributes as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "attr-only": {
+ "description": "Report any use of key-value pairs as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "args-on-sep-lines": {
+ "description": "Report two or more arguments on the same line.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Report the use of string literals as log keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-keys": {
+ "description": "Report the use of log keys that are not explicitly allowed.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "forbidden-keys": {
+ "description": "Report the use of forbidden log keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "key-naming-case": {
+ "description": "Report log keys that do not match a particular naming case.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "custom-funcs": {
+ "description": "Analyze custom functions in addition to the standard log/slog functions.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/settings/definitions/sloglintCustomFunc"
+ }
+ }
+ }
+ },
+ "sloglintCustomFunc": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "The full name of the function, including the package. If the function is a method, the receiver type must be wrapped in parentheses.",
+ "type": "string"
+ },
+ "msg-pos": {
+ "description": "The position of the \"msg string\" argument in the function signature, starting from 0. If there is no message in the function, a negative value must be passed.",
+ "type": "integer"
+ },
+ "args-pos": {
+ "description": "The position of the \"args ...any\" argument in the function signature, starting from 0. If there are no arguments in the function, a negative value must be passed.",
+ "type": "integer"
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "cuddle-max-statements": {
+ "type": "integer",
+ "default": 1
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "bodyclose": {
+ "$ref": "#/definitions/settings/definitions/bodycloseSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "exhaustruct_v5": {
+ "$ref": "#/definitions/settings/definitions/exhaustructv5Settings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gomodguard_v2": {
+ "$ref": "#/definitions/settings/definitions/gomodguardv2Settings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.next.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.next.jsonschema.json
new file mode 100644
index 00000000..bb4f0398
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.next.jsonschema.json
@@ -0,0 +1,5575 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G116",
+ "G117",
+ "G118",
+ "G119",
+ "G120",
+ "G121",
+ "G122",
+ "G123",
+ "G124",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G408",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602",
+ "G701",
+ "G702",
+ "G703",
+ "G704",
+ "G705",
+ "G706",
+ "G707",
+ "G708",
+ "G709",
+ "G710"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "inline",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-naming",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported",
+ "unusedmethod"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "atomictypes",
+ "embedlit",
+ "errorsastype",
+ "forvar",
+ "importcomment",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypeassert",
+ "reflecttypefor",
+ "slicesbackward",
+ "slicesclip",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroupgo"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "after-block",
+ "after-decl",
+ "after-defer",
+ "after-expr",
+ "after-go",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "assign",
+ "branch",
+ "cuddle-group",
+ "decl",
+ "defer",
+ "err",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "leading-whitespace",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "trailing-whitespace",
+ "type-switch"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "clickhouselint",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exhaustruct_v5",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "gomodguard_v2",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "skip-raw-strings": {
+ "description": "Skip raw string literals (backtick-delimited) from duplicate word checking.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bodycloseSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-consumption": {
+ "description": "Check that the response body is consumed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructv5Settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enforce-patterns": {
+ "description": "List of regular expressions to match type names that should be checked.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-patterns":{
+ "description": "List of regular expressions to match type names that should be skipped from checking.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "optional-patterns": {
+ "description": "List of regular expressions to match type names where all fields are treated as optional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty":{
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-patterns": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-mode":{
+ "description": "When true, only types marked with //exhaustruct:enforce directive or matching enforce-rx patterns are checked.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-loops": {
+ "description": "Disable detection of fat contexts in function literals.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-function-literals": {
+ "description": "Disable detection of fat contexts in function literals.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ },
+ "function": {
+ "description": "Checks that exported functions are placed before unexported functions.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "exclude-types": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Assignment",
+ "Binary",
+ "Case",
+ "Return",
+ "Call",
+ "CompositeLit"
+ ]
+ }
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-tests": {
+ "description": "Ignore strings from test files",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-functions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-map-keys": {
+ "description": "Ignore string literals used as map keys",
+ "type": "boolean"
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ },
+ "extra": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "group-params": {
+ "type": "boolean",
+ "default": false
+ },
+ "clothe-returns": {
+ "type": "boolean",
+ "default": false
+ },
+ "balance-calls": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "replace-allow-all": {
+ "description": "Allow all `replace` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardv2Settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-replace-directives": {
+ "type": "boolean"
+ },
+ "allowed": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "enum": ["", "exact", "prefix", "regex"],
+ "default": "exact"
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "type": "string"
+ },
+ "reason": {
+ "type": "string"
+ },
+ "recommendations": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "unusedmethod": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-unused-named-returns": {
+ "description": "Allow named returns in the signature but report them if referenced in the body or used by a naked return.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-cleanup": {
+ "description": "Check that defer is not used with t.Parallel (use t.Cleanup instead).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-global": {
+ "description": "Report the use of global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "context": {
+ "description": "Report the use of functions without a context.Context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Report dynamic log messages, such as those that are built with fmt.Sprintf.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Report log messages that do not match a particular style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Report the use of both key-value pairs and attributes within a single function call.",
+ "type": "boolean",
+ "default": true
+ },
+ "kv-only": {
+ "description": "Report any use of attributes as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "attr-only": {
+ "description": "Report any use of key-value pairs as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "args-on-sep-lines": {
+ "description": "Report two or more arguments on the same line.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Report the use of string literals as log keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-keys": {
+ "description": "Report the use of log keys that are not explicitly allowed.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "forbidden-keys": {
+ "description": "Report the use of forbidden log keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "key-naming-case": {
+ "description": "Report log keys that do not match a particular naming case.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "custom-funcs": {
+ "description": "Analyze custom functions in addition to the standard log/slog functions.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/settings/definitions/sloglintCustomFunc"
+ }
+ }
+ }
+ },
+ "sloglintCustomFunc": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "The full name of the function, including the package. If the function is a method, the receiver type must be wrapped in parentheses.",
+ "type": "string"
+ },
+ "msg-pos": {
+ "description": "The position of the \"msg string\" argument in the function signature, starting from 0. If there is no message in the function, a negative value must be passed.",
+ "type": "integer"
+ },
+ "args-pos": {
+ "description": "The position of the \"args ...any\" argument in the function signature, starting from 0. If there are no arguments in the function, a negative value must be passed.",
+ "type": "integer"
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "cuddle-max-statements": {
+ "type": "integer",
+ "default": 1
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "bodyclose": {
+ "$ref": "#/definitions/settings/definitions/bodycloseSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "exhaustruct_v5": {
+ "$ref": "#/definitions/settings/definitions/exhaustructv5Settings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gomodguard_v2": {
+ "$ref": "#/definitions/settings/definitions/gomodguardv2Settings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.57.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.57.jsonschema.json
new file mode 100644
index 00000000..a97c0d42
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.57.jsonschema.json
@@ -0,0 +1,3480 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "goerr113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomnd",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "typecheck",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "github-actions",
+ "teamcity"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore": {
+ "description": "DEPRECATED: use `exclude-functions` instead. Comma-separated list of pairs of the form \"pkg:regex\".",
+ "type": "string",
+ "default": "fmt:.*"
+ },
+ "exclude": {
+ "description": "DEPRECATED: use `exclude-functions` instead. Path to a file containing a list of functions to exclude from checking.",
+ "type": "string",
+ "examples": ["/path/to/file.txt"]
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print.*$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "DEPRECATED: use 'sections' and 'prefix(github.com/org/project)' instead.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ },
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "lang-version": {
+ "description": "Select the Go version to target.",
+ "type": "string",
+ "default": "1.15"
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "go": {
+ "description": "Targeted Go version",
+ "type": "string",
+ "default": "1.13"
+ },
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "Order of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context-only": {
+ "description": "Enforce using methods that accept a context.",
+ "type": "boolean",
+ "default": false
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "go": {
+ "description": "Targeted Go version",
+ "type": "string",
+ "default": "1.13"
+ },
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "go": {
+ "description": "Targeted Go version",
+ "type": "string",
+ "default": "1.13"
+ },
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "go-require",
+ "float-compare",
+ "len",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ }
+ },
+ "disable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "go-require",
+ "float-compare",
+ "len",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string"
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string"
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"]
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "os-dev-null": {
+ "description": "Suggest the use of os.DevNull.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "syslog-priority": {
+ "description": "Suggest the use of syslog.Priority.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated-strict": {
+ "description": "To follow strict Go generated file convention",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.58.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.58.jsonschema.json
new file mode 100644
index 00000000..d0bdc8d7
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.58.jsonschema.json
@@ -0,0 +1,3638 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "typecheck",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "github-actions",
+ "teamcity"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print.*$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "Order of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "go-require",
+ "float-compare",
+ "len",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ }
+ },
+ "disable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "go-require",
+ "float-compare",
+ "len",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string"
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string"
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"]
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated-strict": {
+ "description": "To follow strict Go generated file convention",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.59.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.59.jsonschema.json
new file mode 100644
index 00000000..cc3e6365
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.59.jsonschema.json
@@ -0,0 +1,3766 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "typecheck",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print.*$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.60.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.60.jsonschema.json
new file mode 100644
index 00000000..b8920ae0
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.60.jsonschema.json
@@ -0,0 +1,3792 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "typecheck",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print.*$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions if format string is used.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.61.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.61.jsonschema.json
new file mode 100644
index 00000000..a574b019
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.61.jsonschema.json
@@ -0,0 +1,3797 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentedOutCode",
+ "commentedOutImport",
+ "commentFormatting",
+ "defaultCaseOrder",
+ "deferUnlambda",
+ "deferInLoop",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringsCompare",
+ "stringXbytes",
+ "suspiciousSorting",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeCmpSimplify",
+ "timeExprSimplify",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "deadcode",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "execinquery",
+ "exhaustive",
+ "exhaustivestruct",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "golint",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "ifshort",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "interfacer",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "maligned",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosnakecase",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "revive",
+ "rowserrcheck",
+ "scopelint",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "structcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varcheck",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ },
+ "default": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "float-compare",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "empty",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions if format string is used.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.62.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.62.jsonschema.json
new file mode 100644
index 00000000..3ca3593b
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.62.jsonschema.json
@@ -0,0 +1,3860 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exportloopref",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtype": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iface": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.63.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.63.jsonschema.json
new file mode 100644
index 00000000..c54dd690
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.63.jsonschema.json
@@ -0,0 +1,4082 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range",
+ "range-val-address",
+ "range-val-in-closure",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exportloopref",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtype": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iface": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetesting": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.64.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.64.jsonschema.json
new file mode 100644
index 00000000..b265c1a8
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.64.jsonschema.json
@@ -0,0 +1,4224 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontext": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtype": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iface": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetesting": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "lax"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "default": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "stdErrorHandling",
+ "commonFalsePositives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "EXC0001",
+ "EXC0002",
+ "EXC0003",
+ "EXC0004",
+ "EXC0005",
+ "EXC0006",
+ "EXC0007",
+ "EXC0008",
+ "EXC0009",
+ "EXC0010",
+ "EXC0011",
+ "EXC0012",
+ "EXC0013",
+ "EXC0014",
+ "EXC0015"
+ ]
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.jsonschema.json
new file mode 100644
index 00000000..b265c1a8
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v1.jsonschema.json
@@ -0,0 +1,4224 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "linters": {
+ "$comment": "anyOf with enum is used to allow auto completion of non-custom linters",
+ "description": "Linters usable.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "gci",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "gofmt",
+ "gofumpt",
+ "goheader",
+ "goimports",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "tenv",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "default": "stdout",
+ "anyOf": [
+ {
+ "enum": [ "stdout", "stderr" ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "format": {
+ "default": "colored-line-number",
+ "enum": [
+ "colored-line-number",
+ "line-number",
+ "json",
+ "colored-tab",
+ "tab",
+ "html",
+ "checkstyle",
+ "code-climate",
+ "junit-xml",
+ "junit-xml-extended",
+ "github-actions",
+ "teamcity",
+ "sarif"
+ ]
+ }
+ },
+ "required": ["format"]
+ }
+ },
+ "print-issued-lines": {
+ "description": "Print lines of code with issue.",
+ "type": "boolean",
+ "default": true
+ },
+ "print-linter-name": {
+ "description": "Print linter name in the end of issue text.",
+ "type": "boolean",
+ "default": true
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": false
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ },
+ "sort-results": {
+ "description": "Sort results by: filepath, line and column.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "linters-settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-test": {
+ "description": "Ignore *_test.go files.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bidichk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclop": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-tests": {
+ "description": "Should the linter execute on test files as well",
+ "type": "boolean",
+ "default": false
+ },
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsled": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "dupl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjson": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustive": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "check-generated": {
+ "description": "Check switch statements in generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustruct": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontext": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "examples": ["^print(ln)?$"],
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "p": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ "funlen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gci": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "skip-generated": {
+ "description": "Skip generated files.",
+ "type": "boolean",
+ "default": true
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtype": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconst": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocritic": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocyclo": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godot": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godox": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "interfacebloat": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumpt": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheader": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimports": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.",
+ "type": "string",
+ "examples": ["github.com/org/project"]
+ }
+ }
+ },
+ "gomoddirectives": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local_replace_directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosimple": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "gosec": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "exclude-generated": {
+ "description": "Exclude generated files",
+ "type": "boolean",
+ "default": false
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitan": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-tests": {
+ "description": "Ignore test files.",
+ "type": "boolean",
+ "default": false
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govet": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iface": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importas": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lll": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidx": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezero": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspell": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-words": {
+ "description": "List of words to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttag": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedret": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnil": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturn": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mnd": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturns": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "prealloc": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclared": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "Comma-separated list of predeclared identifiers to not report on.",
+ "type": "string"
+ },
+ "q": {
+ "description": "Include method names and field names (i.e., qualified names) in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "revive": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "ignore-generated-header": {
+ "type": "boolean"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "stylecheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": ["all"]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": [
+ "all",
+ "-ST1000",
+ "-ST1003",
+ "-ST1016",
+ "-ST1020",
+ "-ST1021",
+ "-ST1022"
+ ]
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalign": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelle": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tenv": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "all": {
+ "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "testifylint": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackage": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelper": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvars": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetesting": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvert": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelen": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespace": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheck": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreSigRegexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignorePackageGlobs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignoreInterfaceRegexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wsl": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvar": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "custom": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "enable-all": {
+ "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.",
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "description": "Allow to use different presets of linters",
+ "type": "array",
+ "items": {
+ "enum": [
+ "bugs",
+ "comment",
+ "complexity",
+ "error",
+ "format",
+ "import",
+ "metalinter",
+ "module",
+ "performance",
+ "sql",
+ "style",
+ "test",
+ "unused"
+ ]
+ }
+ },
+ "fast": {
+ "description": "Enable run of fast linters.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "lax"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "default": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "stdErrorHandling",
+ "commonFalsePositives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-rules": {
+ "description": "Exclude configuration per-path, per-linter, per-text and per-source",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "exclude-use-default": {
+ "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-case-sensitive": {
+ "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-generated": {
+ "description": "Mode of the generated files analysis.",
+ "enum": ["lax", "strict", "disable"],
+ "default": "lax"
+ },
+ "exclude-dirs": {
+ "description": "Which directories to exclude: issues from them won't be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": ["generated.*"]
+ },
+ "default": [],
+ "examples": [["src/external_libs", "autogenerated_by_my_lib"]]
+ },
+ "exclude-dirs-use-default": {
+ "description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
+ "type": "boolean",
+ "default": true
+ },
+ "exclude-files": {
+ "description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
+ "type": "array",
+ "items": {
+ "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
+ "type": "string",
+ "examples": [".*\\.my\\.go$"]
+ },
+ "default": [],
+ "examples": [[".*\\.my\\.go$", "lib/bad.go"]]
+ },
+ "include": {
+ "description": "The list of ids of default excludes to include or disable.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "EXC0001",
+ "EXC0002",
+ "EXC0003",
+ "EXC0004",
+ "EXC0005",
+ "EXC0006",
+ "EXC0007",
+ "EXC0008",
+ "EXC0009",
+ "EXC0010",
+ "EXC0011",
+ "EXC0012",
+ "EXC0013",
+ "EXC0014",
+ "EXC0015"
+ ]
+ },
+ "default": []
+ },
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-severity": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "case-sensitive": {
+ "description": "If set to true, severity-rules regular expressions become case sensitive.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linters"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default-severity"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.0.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.0.jsonschema.json
new file mode 100644
index 00000000..437943b5
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.0.jsonschema.json
@@ -0,0 +1,4738 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-strings": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "string"
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.1.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.1.jsonschema.json
new file mode 100644
index 00000000..0f2ef5fc
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.1.jsonschema.json
@@ -0,0 +1,4790 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": true
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.10.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.10.jsonschema.json
new file mode 100644
index 00000000..7fa4a12d
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.10.jsonschema.json
@@ -0,0 +1,5285 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G116",
+ "G117",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602",
+ "G701",
+ "G702",
+ "G703",
+ "G704",
+ "G705",
+ "G706"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace",
+ "after-block"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.11.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.11.jsonschema.json
new file mode 100644
index 00000000..38b3e77a
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.11.jsonschema.json
@@ -0,0 +1,5295 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G116",
+ "G117",
+ "G118",
+ "G119",
+ "G120",
+ "G121",
+ "G122",
+ "G123",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G408",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602",
+ "G701",
+ "G702",
+ "G703",
+ "G704",
+ "G705",
+ "G706",
+ "G707"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-naming",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace",
+ "after-block"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.12.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.12.jsonschema.json
new file mode 100644
index 00000000..0ac9d577
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.12.jsonschema.json
@@ -0,0 +1,5438 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G113",
+ "G114",
+ "G115",
+ "G116",
+ "G117",
+ "G118",
+ "G119",
+ "G120",
+ "G121",
+ "G122",
+ "G123",
+ "G124",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G408",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602",
+ "G701",
+ "G702",
+ "G703",
+ "G704",
+ "G705",
+ "G706",
+ "G707",
+ "G708",
+ "G709",
+ "G710"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "inline",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-naming",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "after-block",
+ "after-decl",
+ "after-defer",
+ "after-expr",
+ "after-go",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "assign",
+ "branch",
+ "cuddle-group",
+ "decl",
+ "defer",
+ "err",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "leading-whitespace",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "trailing-whitespace",
+ "type-switch"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "clickhouselint",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "gomodguard_v2",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "bodycloseSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-consumption": {
+ "description": "Check that the response body is consumed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ },
+ "function": {
+ "description": "Checks that exported functions are placed before unexported functions.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-tests": {
+ "description": "Ignore strings from test files",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-functions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardv2Settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-replace-directives": {
+ "type": "boolean"
+ },
+ "allowed": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "enum": ["", "exact", "prefix", "regex"],
+ "default": "exact"
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["module"],
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "match-type": {
+ "type": "string"
+ },
+ "reason": {
+ "type": "string"
+ },
+ "recommendations": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-cleanup": {
+ "description": "Check that defer is not used with t.Parallel (use t.Cleanup instead).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-global": {
+ "description": "Report the use of global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "context": {
+ "description": "Report the use of functions without a context.Context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Report dynamic log messages, such as those that are built with fmt.Sprintf.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Report log messages that do not match a particular style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Report the use of both key-value pairs and attributes within a single function call.",
+ "type": "boolean",
+ "default": true
+ },
+ "kv-only": {
+ "description": "Report any use of attributes as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "attr-only": {
+ "description": "Report any use of key-value pairs as function call arguments.",
+ "type": "boolean",
+ "default": false
+ },
+ "args-on-sep-lines": {
+ "description": "Report two or more arguments on the same line.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Report the use of string literals as log keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-keys": {
+ "description": "Report the use of log keys that are not explicitly allowed.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "forbidden-keys": {
+ "description": "Report the use of forbidden log keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "key-naming-case": {
+ "description": "Report log keys that do not match a particular naming case.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "custom-funcs": {
+ "description": "Analyze custom functions in addition to the standard log/slog functions.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/settings/definitions/sloglintCustomFunc"
+ }
+ }
+ }
+ },
+ "sloglintCustomFunc": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "The full name of the function, including the package. If the function is a method, the receiver type must be wrapped in parentheses.",
+ "type": "string"
+ },
+ "msg-pos": {
+ "description": "The position of the \"msg string\" argument in the function signature, starting from 0. If there is no message in the function, a negative value must be passed.",
+ "type": "integer"
+ },
+ "args-pos": {
+ "description": "The position of the \"args ...any\" argument in the function signature, starting from 0. If there are no arguments in the function, a negative value must be passed.",
+ "type": "integer"
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "cuddle-max-statements": {
+ "type": "integer",
+ "default": 1
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "bodyclose": {
+ "$ref": "#/definitions/settings/definitions/bodycloseSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gomodguard_v2": {
+ "$ref": "#/definitions/settings/definitions/gomodguardv2Settings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.2.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.2.jsonschema.json
new file mode 100644
index 00000000..3e51264f
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.2.jsonschema.json
@@ -0,0 +1,4901 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.3.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.3.jsonschema.json
new file mode 100644
index 00000000..7c484052
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.3.jsonschema.json
@@ -0,0 +1,4907 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.4.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.4.jsonschema.json
new file mode 100644
index 00000000..67cd80a5
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.4.jsonschema.json
@@ -0,0 +1,4929 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "useless-break",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.5.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.5.jsonschema.json
new file mode 100644
index 00000000..f471fd3d
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.5.jsonschema.json
@@ -0,0 +1,5081 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "ioutilDeprecated",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `// `, or `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Fix found issues (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.6.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.6.jsonschema.json
new file mode 100644
index 00000000..e2f59663
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.6.jsonschema.json
@@ -0,0 +1,5136 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "bloop",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `// `, or `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.7.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.7.jsonschema.json
new file mode 100644
index 00000000..accf61f9
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.7.jsonschema.json
@@ -0,0 +1,5144 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "bloop",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `// `, or `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.8.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.8.jsonschema.json
new file mode 100644
index 00000000..675beedd
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.8.jsonschema.json
@@ -0,0 +1,5223 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G116",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "bloop",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.9.jsonschema.json b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.9.jsonschema.json
new file mode 100644
index 00000000..38b3590c
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/golangci.v2.9.jsonschema.json
@@ -0,0 +1,5278 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/golangci-lint.json",
+ "definitions": {
+ "gocritic-checks": {
+ "enum": [
+ "appendAssign",
+ "appendCombine",
+ "argOrder",
+ "assignOp",
+ "badCall",
+ "badCond",
+ "badLock",
+ "badRegexp",
+ "badSorting",
+ "badSyncOnceFunc",
+ "boolExprSimplify",
+ "builtinShadow",
+ "builtinShadowDecl",
+ "captLocal",
+ "caseOrder",
+ "codegenComment",
+ "commentFormatting",
+ "commentedOutCode",
+ "commentedOutImport",
+ "defaultCaseOrder",
+ "deferInLoop",
+ "deferUnlambda",
+ "deprecatedComment",
+ "docStub",
+ "dupArg",
+ "dupBranchBody",
+ "dupCase",
+ "dupImport",
+ "dupOption",
+ "dupSubExpr",
+ "dynamicFmtString",
+ "elseif",
+ "emptyDecl",
+ "emptyFallthrough",
+ "emptyStringTest",
+ "equalFold",
+ "evalOrder",
+ "exitAfterDefer",
+ "exposedSyncMutex",
+ "externalErrorReassign",
+ "filepathJoin",
+ "flagDeref",
+ "flagName",
+ "hexLiteral",
+ "httpNoBody",
+ "hugeParam",
+ "ifElseChain",
+ "importShadow",
+ "indexAlloc",
+ "initClause",
+ "mapKey",
+ "methodExprCall",
+ "nestingReduce",
+ "newDeref",
+ "nilValReturn",
+ "octalLiteral",
+ "offBy1",
+ "paramTypeCombine",
+ "preferDecodeRune",
+ "preferFilepathJoin",
+ "preferFprint",
+ "preferStringWriter",
+ "preferWriteByte",
+ "ptrToRefParam",
+ "rangeAppendAll",
+ "rangeExprCopy",
+ "rangeValCopy",
+ "redundantSprint",
+ "regexpMust",
+ "regexpPattern",
+ "regexpSimplify",
+ "returnAfterHttpError",
+ "ruleguard",
+ "singleCaseSwitch",
+ "sliceClear",
+ "sloppyLen",
+ "sloppyReassign",
+ "sloppyTypeAssert",
+ "sortSlice",
+ "sprintfQuotedString",
+ "sqlQuery",
+ "stringConcatSimplify",
+ "stringXbytes",
+ "stringsCompare",
+ "switchTrue",
+ "syncMapLoadAndDelete",
+ "timeExprSimplify",
+ "todoCommentWithoutDetail",
+ "tooManyResultsChecker",
+ "truncateCmp",
+ "typeAssertChain",
+ "typeDefFirst",
+ "typeSwitchVar",
+ "typeUnparen",
+ "uncheckedInlineErr",
+ "underef",
+ "unlabelStmt",
+ "unlambda",
+ "unnamedResult",
+ "unnecessaryBlock",
+ "unnecessaryDefer",
+ "unslice",
+ "valSwap",
+ "weakCond",
+ "whyNoLint",
+ "wrapperFunc",
+ "yodaStyleExpr",
+ "zeroByteRepeat"
+ ]
+ },
+ "gocritic-tags": {
+ "enum": [
+ "diagnostic",
+ "style",
+ "performance",
+ "experimental",
+ "opinionated",
+ "security"
+ ]
+ },
+ "staticcheck-checks": {
+ "enum": [
+ "*",
+ "all",
+ "SA*",
+ "-SA*",
+ "SA1*",
+ "-SA1*",
+ "SA1000",
+ "-SA1000",
+ "SA1001",
+ "-SA1001",
+ "SA1002",
+ "-SA1002",
+ "SA1003",
+ "-SA1003",
+ "SA1004",
+ "-SA1004",
+ "SA1005",
+ "-SA1005",
+ "SA1006",
+ "-SA1006",
+ "SA1007",
+ "-SA1007",
+ "SA1008",
+ "-SA1008",
+ "SA1010",
+ "-SA1010",
+ "SA1011",
+ "-SA1011",
+ "SA1012",
+ "-SA1012",
+ "SA1013",
+ "-SA1013",
+ "SA1014",
+ "-SA1014",
+ "SA1015",
+ "-SA1015",
+ "SA1016",
+ "-SA1016",
+ "SA1017",
+ "-SA1017",
+ "SA1018",
+ "-SA1018",
+ "SA1019",
+ "-SA1019",
+ "SA1020",
+ "-SA1020",
+ "SA1021",
+ "-SA1021",
+ "SA1023",
+ "-SA1023",
+ "SA1024",
+ "-SA1024",
+ "SA1025",
+ "-SA1025",
+ "SA1026",
+ "-SA1026",
+ "SA1027",
+ "-SA1027",
+ "SA1028",
+ "-SA1028",
+ "SA1029",
+ "-SA1029",
+ "SA1030",
+ "-SA1030",
+ "SA1031",
+ "-SA1031",
+ "SA1032",
+ "-SA1032",
+ "SA2*",
+ "-SA2*",
+ "SA2000",
+ "-SA2000",
+ "SA2001",
+ "-SA2001",
+ "SA2002",
+ "-SA2002",
+ "SA2003",
+ "-SA2003",
+ "SA3*",
+ "-SA3*",
+ "SA3000",
+ "-SA3000",
+ "SA3001",
+ "-SA3001",
+ "SA4*",
+ "-SA4*",
+ "SA4000",
+ "-SA4000",
+ "SA4001",
+ "-SA4001",
+ "SA4003",
+ "-SA4003",
+ "SA4004",
+ "-SA4004",
+ "SA4005",
+ "-SA4005",
+ "SA4006",
+ "-SA4006",
+ "SA4008",
+ "-SA4008",
+ "SA4009",
+ "-SA4009",
+ "SA4010",
+ "-SA4010",
+ "SA4011",
+ "-SA4011",
+ "SA4012",
+ "-SA4012",
+ "SA4013",
+ "-SA4013",
+ "SA4014",
+ "-SA4014",
+ "SA4015",
+ "-SA4015",
+ "SA4016",
+ "-SA4016",
+ "SA4017",
+ "-SA4017",
+ "SA4018",
+ "-SA4018",
+ "SA4019",
+ "-SA4019",
+ "SA4020",
+ "-SA4020",
+ "SA4021",
+ "-SA4021",
+ "SA4022",
+ "-SA4022",
+ "SA4023",
+ "-SA4023",
+ "SA4024",
+ "-SA4024",
+ "SA4025",
+ "-SA4025",
+ "SA4026",
+ "-SA4026",
+ "SA4027",
+ "-SA4027",
+ "SA4028",
+ "-SA4028",
+ "SA4029",
+ "-SA4029",
+ "SA4030",
+ "-SA4030",
+ "SA4031",
+ "-SA4031",
+ "SA4032",
+ "-SA4032",
+ "SA5*",
+ "-SA5*",
+ "SA5000",
+ "-SA5000",
+ "SA5001",
+ "-SA5001",
+ "SA5002",
+ "-SA5002",
+ "SA5003",
+ "-SA5003",
+ "SA5004",
+ "-SA5004",
+ "SA5005",
+ "-SA5005",
+ "SA5007",
+ "-SA5007",
+ "SA5008",
+ "-SA5008",
+ "SA5009",
+ "-SA5009",
+ "SA5010",
+ "-SA5010",
+ "SA5011",
+ "-SA5011",
+ "SA5012",
+ "-SA5012",
+ "SA6*",
+ "-SA6*",
+ "SA6000",
+ "-SA6000",
+ "SA6001",
+ "-SA6001",
+ "SA6002",
+ "-SA6002",
+ "SA6003",
+ "-SA6003",
+ "SA6005",
+ "-SA6005",
+ "SA6006",
+ "-SA6006",
+ "SA9*",
+ "-SA9*",
+ "SA9001",
+ "-SA9001",
+ "SA9002",
+ "-SA9002",
+ "SA9003",
+ "-SA9003",
+ "SA9004",
+ "-SA9004",
+ "SA9005",
+ "-SA9005",
+ "SA9006",
+ "-SA9006",
+ "SA9007",
+ "-SA9007",
+ "SA9008",
+ "-SA9008",
+ "SA9009",
+ "-SA9009",
+ "ST*",
+ "-ST*",
+ "ST1*",
+ "-ST1*",
+ "ST1000",
+ "-ST1000",
+ "ST1001",
+ "-ST1001",
+ "ST1003",
+ "-ST1003",
+ "ST1005",
+ "-ST1005",
+ "ST1006",
+ "-ST1006",
+ "ST1008",
+ "-ST1008",
+ "ST1011",
+ "-ST1011",
+ "ST1012",
+ "-ST1012",
+ "ST1013",
+ "-ST1013",
+ "ST1015",
+ "-ST1015",
+ "ST1016",
+ "-ST1016",
+ "ST1017",
+ "-ST1017",
+ "ST1018",
+ "-ST1018",
+ "ST1019",
+ "-ST1019",
+ "ST1020",
+ "-ST1020",
+ "ST1021",
+ "-ST1021",
+ "ST1022",
+ "-ST1022",
+ "ST1023",
+ "-ST1023",
+ "S*",
+ "-S*",
+ "S1*",
+ "-S1*",
+ "S1000",
+ "-S1000",
+ "S1001",
+ "-S1001",
+ "S1002",
+ "-S1002",
+ "S1003",
+ "-S1003",
+ "S1004",
+ "-S1004",
+ "S1005",
+ "-S1005",
+ "S1006",
+ "-S1006",
+ "S1007",
+ "-S1007",
+ "S1008",
+ "-S1008",
+ "S1009",
+ "-S1009",
+ "S1010",
+ "-S1010",
+ "S1011",
+ "-S1011",
+ "S1012",
+ "-S1012",
+ "S1016",
+ "-S1016",
+ "S1017",
+ "-S1017",
+ "S1018",
+ "-S1018",
+ "S1019",
+ "-S1019",
+ "S1020",
+ "-S1020",
+ "S1021",
+ "-S1021",
+ "S1023",
+ "-S1023",
+ "S1024",
+ "-S1024",
+ "S1025",
+ "-S1025",
+ "S1028",
+ "-S1028",
+ "S1029",
+ "-S1029",
+ "S1030",
+ "-S1030",
+ "S1031",
+ "-S1031",
+ "S1032",
+ "-S1032",
+ "S1033",
+ "-S1033",
+ "S1034",
+ "-S1034",
+ "S1035",
+ "-S1035",
+ "S1036",
+ "-S1036",
+ "S1037",
+ "-S1037",
+ "S1038",
+ "-S1038",
+ "S1039",
+ "-S1039",
+ "S1040",
+ "-S1040",
+ "QF*",
+ "-QF*",
+ "QF1*",
+ "-QF1*",
+ "QF1001",
+ "-QF1001",
+ "QF1002",
+ "-QF1002",
+ "QF1003",
+ "-QF1003",
+ "QF1004",
+ "-QF1004",
+ "QF1005",
+ "-QF1005",
+ "QF1006",
+ "-QF1006",
+ "QF1007",
+ "-QF1007",
+ "QF1008",
+ "-QF1008",
+ "QF1009",
+ "-QF1009",
+ "QF1010",
+ "-QF1010",
+ "QF1011",
+ "-QF1011",
+ "QF1012",
+ "-QF1012"
+ ]
+ },
+ "godoclint-rules": {
+ "enum": [
+ "pkg-doc",
+ "single-pkg-doc",
+ "require-pkg-doc",
+ "start-with-name",
+ "require-doc",
+ "deprecated",
+ "max-len",
+ "no-unused-link",
+ "require-stdlib-doclink"
+ ]
+ },
+ "gosec-rules": {
+ "enum": [
+ "G101",
+ "G102",
+ "G103",
+ "G104",
+ "G106",
+ "G107",
+ "G108",
+ "G109",
+ "G110",
+ "G111",
+ "G112",
+ "G114",
+ "G115",
+ "G116",
+ "G201",
+ "G202",
+ "G203",
+ "G204",
+ "G301",
+ "G302",
+ "G303",
+ "G304",
+ "G305",
+ "G306",
+ "G307",
+ "G401",
+ "G402",
+ "G403",
+ "G404",
+ "G405",
+ "G406",
+ "G501",
+ "G502",
+ "G503",
+ "G504",
+ "G505",
+ "G506",
+ "G507",
+ "G601",
+ "G602"
+ ]
+ },
+ "govet-analyzers": {
+ "enum": [
+ "appends",
+ "asmdecl",
+ "assign",
+ "atomic",
+ "atomicalign",
+ "bools",
+ "buildtag",
+ "cgocall",
+ "composites",
+ "copylocks",
+ "deepequalerrors",
+ "defers",
+ "directive",
+ "errorsas",
+ "fieldalignment",
+ "findcall",
+ "framepointer",
+ "hostport",
+ "httpmux",
+ "httpresponse",
+ "ifaceassert",
+ "loopclosure",
+ "lostcancel",
+ "nilfunc",
+ "nilness",
+ "printf",
+ "reflectvaluecompare",
+ "shadow",
+ "shift",
+ "sigchanyzer",
+ "slog",
+ "sortslice",
+ "stdmethods",
+ "stdversion",
+ "stringintconv",
+ "structtag",
+ "testinggoroutine",
+ "tests",
+ "timeformat",
+ "unmarshal",
+ "unreachable",
+ "unsafeptr",
+ "unusedresult",
+ "unusedwrite",
+ "waitgroup"
+ ]
+ },
+ "revive-rules": {
+ "enum": [
+ "add-constant",
+ "argument-limit",
+ "atomic",
+ "banned-characters",
+ "bare-return",
+ "blank-imports",
+ "bool-literal-in-expr",
+ "call-to-gc",
+ "cognitive-complexity",
+ "comment-spacings",
+ "comments-density",
+ "confusing-naming",
+ "confusing-results",
+ "constant-logical-expr",
+ "context-as-argument",
+ "context-keys-type",
+ "cyclomatic",
+ "datarace",
+ "deep-exit",
+ "defer",
+ "dot-imports",
+ "duplicated-imports",
+ "early-return",
+ "empty-block",
+ "empty-lines",
+ "enforce-map-style",
+ "enforce-repeated-arg-type-style",
+ "enforce-slice-style",
+ "enforce-switch-style",
+ "epoch-naming",
+ "error-naming",
+ "error-return",
+ "error-strings",
+ "errorf",
+ "exported",
+ "file-header",
+ "file-length-limit",
+ "filename-format",
+ "flag-parameter",
+ "forbidden-call-in-wg-go",
+ "function-length",
+ "function-result-limit",
+ "get-return",
+ "identical-branches",
+ "identical-ifelseif-branches",
+ "identical-ifelseif-conditions",
+ "identical-switch-branches",
+ "identical-switch-conditions",
+ "if-return",
+ "import-alias-naming",
+ "import-shadowing",
+ "imports-blocklist",
+ "increment-decrement",
+ "indent-error-flow",
+ "inefficient-map-lookup",
+ "line-length-limit",
+ "max-control-nesting",
+ "max-public-structs",
+ "modifies-parameter",
+ "modifies-value-receiver",
+ "nested-structs",
+ "optimize-operands-order",
+ "package-comments",
+ "package-directory-mismatch",
+ "range-val-address",
+ "range-val-in-closure",
+ "range",
+ "receiver-naming",
+ "redefines-builtin-id",
+ "redundant-build-tag",
+ "redundant-import-alias",
+ "redundant-test-main-exit",
+ "string-format",
+ "string-of-int",
+ "struct-tag",
+ "superfluous-else",
+ "time-date",
+ "time-equal",
+ "time-naming",
+ "unchecked-type-assertion",
+ "unconditional-recursion",
+ "unexported-naming",
+ "unexported-return",
+ "unhandled-error",
+ "unnecessary-format",
+ "unnecessary-if",
+ "unnecessary-stmt",
+ "unreachable-code",
+ "unsecure-url-scheme",
+ "unused-parameter",
+ "unused-receiver",
+ "use-any",
+ "use-errors-new",
+ "use-fmt-print",
+ "use-slices-sort",
+ "use-waitgroup-go",
+ "useless-break",
+ "useless-fallthrough",
+ "var-declaration",
+ "var-naming",
+ "waitgroup-by-value"
+ ]
+ },
+ "iface-analyzers": {
+ "enum": [
+ "identical",
+ "unused",
+ "opaque",
+ "unexported"
+ ]
+ },
+ "tagliatelle-cases": {
+ "enum": [
+ "",
+ "camel",
+ "pascal",
+ "kebab",
+ "snake",
+ "goCamel",
+ "goPascal",
+ "goKebab",
+ "goSnake",
+ "upper",
+ "upperSnake",
+ "lower",
+ "header"
+ ]
+ },
+ "modernize-analyzers": {
+ "enum": [
+ "any",
+ "fmtappendf",
+ "forvar",
+ "mapsloop",
+ "minmax",
+ "newexpr",
+ "omitzero",
+ "plusbuild",
+ "rangeint",
+ "reflecttypefor",
+ "slicescontains",
+ "slicessort",
+ "stditerators",
+ "stringscut",
+ "stringscutprefix",
+ "stringsseq",
+ "stringsbuilder",
+ "testingcontext",
+ "unsafefuncs",
+ "waitgroup"
+ ]
+ },
+ "wsl-checks": {
+ "enum": [
+ "assign",
+ "branch",
+ "decl",
+ "defer",
+ "expr",
+ "for",
+ "go",
+ "if",
+ "inc-dec",
+ "label",
+ "range",
+ "return",
+ "select",
+ "send",
+ "switch",
+ "type-switch",
+ "append",
+ "assign-exclusive",
+ "assign-expr",
+ "err",
+ "leading-whitespace",
+ "trailing-whitespace",
+ "after-block"
+ ]
+ },
+ "relative-path-modes": {
+ "enum": [
+ "gomod",
+ "gitroot",
+ "cfg",
+ "wd"
+ ]
+ },
+ "simple-format": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ }
+ }
+ },
+ "formats-path" : {
+ "anyOf": [
+ {
+ "enum": [
+ "stdout",
+ "stderr"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "linter-names": {
+ "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters",
+ "description": "Usable linter names.",
+ "anyOf": [
+ {
+ "enum": [
+ "arangolint",
+ "asasalint",
+ "asciicheck",
+ "bidichk",
+ "bodyclose",
+ "canonicalheader",
+ "containedctx",
+ "contextcheck",
+ "copyloopvar",
+ "cyclop",
+ "decorder",
+ "depguard",
+ "dogsled",
+ "dupl",
+ "dupword",
+ "durationcheck",
+ "embeddedstructfieldcheck",
+ "errcheck",
+ "errchkjson",
+ "errname",
+ "errorlint",
+ "exhaustive",
+ "exhaustruct",
+ "exptostd",
+ "fatcontext",
+ "forbidigo",
+ "forcetypeassert",
+ "funcorder",
+ "funlen",
+ "ginkgolinter",
+ "gocheckcompilerdirectives",
+ "gochecknoglobals",
+ "gochecknoinits",
+ "gochecksumtype",
+ "gocognit",
+ "goconst",
+ "gocritic",
+ "gocyclo",
+ "godoclint",
+ "godot",
+ "godox",
+ "err113",
+ "goheader",
+ "gomoddirectives",
+ "gomodguard",
+ "goprintffuncname",
+ "gosec",
+ "gosimple",
+ "gosmopolitan",
+ "govet",
+ "grouper",
+ "iface",
+ "importas",
+ "inamedparam",
+ "ineffassign",
+ "interfacebloat",
+ "intrange",
+ "iotamixing",
+ "ireturn",
+ "lll",
+ "loggercheck",
+ "maintidx",
+ "makezero",
+ "mirror",
+ "misspell",
+ "mnd",
+ "modernize",
+ "musttag",
+ "nakedret",
+ "nestif",
+ "nilerr",
+ "nilnesserr",
+ "nilnil",
+ "nlreturn",
+ "noctx",
+ "noinlineerr",
+ "nolintlint",
+ "nonamedreturns",
+ "nosprintfhostport",
+ "paralleltest",
+ "perfsprint",
+ "prealloc",
+ "predeclared",
+ "promlinter",
+ "protogetter",
+ "reassign",
+ "recvcheck",
+ "revive",
+ "rowserrcheck",
+ "sloglint",
+ "sqlclosecheck",
+ "staticcheck",
+ "stylecheck",
+ "tagalign",
+ "tagliatelle",
+ "testableexamples",
+ "testifylint",
+ "testpackage",
+ "thelper",
+ "tparallel",
+ "unconvert",
+ "unparam",
+ "unused",
+ "usestdlibvars",
+ "usetesting",
+ "varnamelen",
+ "wastedassign",
+ "whitespace",
+ "wrapcheck",
+ "wsl",
+ "wsl_v5",
+ "zerologlint"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "formatter-names": {
+ "description": "Usable formatter names.",
+ "enum": [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
+ "golines",
+ "swaggo"
+ ]
+ },
+ "settings": {
+ "definitions": {
+ "dupwordSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["the", "and", "a"]
+ }
+ },
+ "ignore": {
+ "description": "Keywords used to ignore detection.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["0C0C"]
+ }
+ },
+ "comments-only": {
+ "description": "Checks only comments, skip strings.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "asasalintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "description": "To specify a set of function names to exclude.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["\\.Wrapf"]
+ }
+ },
+ "use-builtin-exclusions": {
+ "description": "To enable/disable the asasalint builtin exclusions of function names.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "bidichkSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "left-to-right-embedding": {
+ "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-embedding": {
+ "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-formatting": {
+ "description": "Disallow: POP-DIRECTIONAL-FORMATTING",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-override": {
+ "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-override": {
+ "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE",
+ "type": "boolean",
+ "default": false
+ },
+ "left-to-right-isolate": {
+ "description": "Disallow: LEFT-TO-RIGHT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "right-to-left-isolate": {
+ "description": "Disallow: RIGHT-TO-LEFT-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "first-strong-isolate": {
+ "description": "Disallow: FIRST-STRONG-ISOLATE",
+ "type": "boolean",
+ "default": false
+ },
+ "pop-directional-isolate": {
+ "description": "Disallow: POP-DIRECTIONAL-ISOLATE",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "cyclopSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-complexity": {
+ "description": "Max complexity the function can have",
+ "type": "integer",
+ "default": 10,
+ "minimum": 0
+ },
+ "package-average": {
+ "description": "Max average complexity in package",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "decorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dec-order": {
+ "type": "array",
+ "default": [["type", "const", "var", "func"]],
+ "items": {
+ "enum": ["type", "const", "var", "func"]
+ }
+ },
+ "ignore-underscore-vars": {
+ "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-order-check": {
+ "description": "Order of declarations is not checked",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-init-func-first-check": {
+ "description": "Allow init func to be anywhere in file",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-dec-num-check": {
+ "description": "Multiple global type, const and var declarations are allowed",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-type-dec-num-check": {
+ "description": "Type declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-const-dec-num-check": {
+ "description": "Const declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ },
+ "disable-var-dec-num-check": {
+ "description": "Var declarations will be ignored for dec num check",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "depguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "rules": {
+ "description": "Rules to apply.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[^.]+$": {
+ "description": "Name of a rule.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "list-mode": {
+ "description": "Used to determine the package matching priority.",
+ "enum": ["original", "strict", "lax"],
+ "default": "original"
+ },
+ "files": {
+ "description": "List of file globs that will match this list of settings to compare against.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "List of allowed packages.",
+ "additionalProperties": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "deny": {
+ "description": "Packages that are not allowed where the value is a suggestion.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "desc": {
+ "description": "Description",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "dogsledSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-blank-identifiers": {
+ "description": "Check assignments with too many blank identifiers.",
+ "type": "integer",
+ "default": 2,
+ "minimum": 0
+ }
+ }
+ },
+ "duplSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "threshold": {
+ "description": "Tokens count to trigger issue.",
+ "type": "integer",
+ "default": 150,
+ "minimum": 0
+ }
+ }
+ },
+ "embeddedstructfieldcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "empty-line": {
+ "description": "Checks that there is an empty space between the embedded fields and regular fields.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-mutex": {
+ "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-type-assertions": {
+ "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`",
+ "type": "boolean",
+ "default": false
+ },
+ "check-blank": {
+ "description": "Report about assignment of errors to blank identifier",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-functions": {
+ "description": "List of functions to exclude from checking, where each entry is a single function to exclude",
+ "type": "array",
+ "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "disable-default-exclusions": {
+ "description": "To disable the errcheck built-in exclude list",
+ "type": "boolean",
+ "default": false
+ },
+ "verbose": {
+ "description": "Display function signature instead of selector",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errchkjsonSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-error-free-encoding": {
+ "type": "boolean",
+ "default": false
+ },
+ "report-no-exported": {
+ "description": "Issue on struct that doesn't have exported fields.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "errorlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "errorf": {
+ "description": "Check whether fmt.Errorf uses the %w verb for formatting errors",
+ "type": "boolean",
+ "default": true
+ },
+ "errorf-multi": {
+ "description": "Permit more than 1 %w verb, valid per Go 1.20",
+ "type": "boolean",
+ "default": true
+ },
+ "asserts": {
+ "description": "Check for plain type assertions and type switches.",
+ "type": "boolean",
+ "default": true
+ },
+ "comparison": {
+ "description": "Check for plain error comparisons",
+ "type": "boolean",
+ "default": true
+ },
+ "allowed-errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "allowed-errors-wildcard": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "err": {
+ "type": "string"
+ },
+ "fun": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "exhaustiveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check": {
+ "description": "Program elements to check for exhaustiveness.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["switch", "map"]
+ }
+ },
+ "explicit-exhaustive-switch": {
+ "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "explicit-exhaustive-map": {
+ "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-case-required": {
+ "description": "Switch statement requires default case even if exhaustive.",
+ "type": "boolean",
+ "default": false
+ },
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-enum-members": {
+ "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness",
+ "type": "string"
+ },
+ "ignore-enum-types": {
+ "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.",
+ "type": "string"
+ },
+ "package-scope-only": {
+ "description": "Consider enums only in package scopes, not in inner scopes.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "exhaustructSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "include": {
+ "description": "List of regular expressions to match struct packages and names.",
+ "type": "array",
+ "examples": [".*\\.Test"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude": {
+ "description": "List of regular expressions to exclude struct packages and names from check.",
+ "type": "array",
+ "examples": ["cobra\\.Command$"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty": {
+ "description": "Allows empty structures, effectively excluding them from the check.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-rx": {
+ "description": "List of regular expressions to match type names that should be allowed to be empty.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-empty-returns": {
+ "description": "Allows empty structures in return statements.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-empty-declarations": {
+ "description": "Allows empty structures in variable declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "fatcontextSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-struct-pointers": {
+ "description": "Check for potential fat contexts in struct pointers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "forbidigoSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude-godoc-examples": {
+ "description": "Exclude code in godoc examples.",
+ "type": "boolean",
+ "default": true
+ },
+ "analyze-types": {
+ "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.",
+ "type": "boolean",
+ "default": true
+ },
+ "forbid": {
+ "description": "List of identifiers to forbid (written using `regexp`)",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Pattern",
+ "type": "string"
+ },
+ "pkg": {
+ "description": "Package",
+ "type": "string"
+ },
+ "msg": {
+ "description": "Message",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "funcorderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "constructor": {
+ "description": "Checks that constructors are placed after the structure declaration.",
+ "type": "boolean",
+ "default": true
+ },
+ "struct-method": {
+ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.",
+ "type": "boolean",
+ "default": true
+ },
+ "alphabetical": {
+ "description": "Checks if the constructors and/or structure methods are sorted alphabetically.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "funlenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "lines": {
+ "description": "Limit lines number per function.",
+ "type": "integer",
+ "default": 60
+ },
+ "statements": {
+ "description": "Limit statements number per function.",
+ "type": "integer",
+ "default": 40
+ },
+ "ignore-comments": {
+ "description": "Ignore comments when counting lines.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "gciSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sections": {
+ "description": "Section configuration to compare against.",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "enum": [
+ "standard",
+ "default",
+ "blank",
+ "dot",
+ "alias",
+ "localmodule"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "default": ["standard", "default"]
+ },
+ "no-inline-comments": {
+ "description": "Checks that no inline Comments are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-prefix-comments": {
+ "description": "Checks that no prefix Comments(comment lines above an import) are present.",
+ "type": "boolean",
+ "default": false
+ },
+ "custom-order": {
+ "description": "Enable custom order of sections.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-lex-order": {
+ "description": "Drops lexical ordering for custom sections.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ginkgolinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "suppress-len-assertion": {
+ "description": "Suppress the wrong length assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-nil-assertion": {
+ "description": "Suppress the wrong nil assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-err-assertion": {
+ "description": "Suppress the wrong error assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-compare-assertion": {
+ "description": "Suppress the wrong comparison assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-async-assertion": {
+ "description": "Suppress the function all in async assertion warning.",
+ "type": "boolean",
+ "default": false
+ },
+ "suppress-type-compare-assertion": {
+ "description": "Suppress warning for comparing values from different types, like int32 and uint32.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-focus-container": {
+ "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-havelen-zero": {
+ "description": "Don't trigger warnings for HaveLen(0).",
+ "type": "boolean",
+ "default": false
+ },
+ "force-expect-to": {
+ "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`",
+ "type": "boolean",
+ "default": false
+ },
+ "validate-async-intervals": {
+ "description": "Best effort validation of async intervals (timeout and polling).",
+ "type": "boolean",
+ "default": false
+ },
+ "forbid-spec-pollution": {
+ "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-succeed": {
+ "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-assertion-description": {
+ "description": "Force adding assertion descriptions to gomega matchers.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-tonot": {
+ "description": "Force using `ToNot`, `ShouldNot` instead of `To(Not())`.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gochecksumtypeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default-signifies-exhaustive": {
+ "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.",
+ "type": "boolean",
+ "default": true
+ },
+ "include-shared-interfaces": {
+ "description": "Include shared interfaces in the exhaustiviness check.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocognitSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimal code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "goconstSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "match-constant": {
+ "description": "Look for existing constants matching the values",
+ "type": "boolean",
+ "default": true
+ },
+ "min-len": {
+ "description": "Minimum length of string constant.",
+ "type": "integer",
+ "default": 3
+ },
+ "min-occurrences": {
+ "description": "Minimum occurrences count to trigger.",
+ "type": "integer",
+ "default": 3
+ },
+ "ignore-calls": {
+ "description": "Ignore when constant is not used as function argument",
+ "type": "boolean",
+ "default": true
+ },
+ "ignore-string-values": {
+ "description": "Exclude strings matching the given regular expression",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "numbers": {
+ "description": "Search also for duplicated numbers.",
+ "type": "boolean",
+ "default": false
+ },
+ "min": {
+ "description": "Minimum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "max": {
+ "description": "Maximum value, only works with `numbers`",
+ "type": "integer",
+ "default": 3
+ },
+ "find-duplicates": {
+ "description": "Detects constants with identical values",
+ "type": "boolean",
+ "default": false
+ },
+ "eval-const-expressions": {
+ "description": "Evaluates of constant expressions like Prefix + \"suffix\"",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocriticSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled-checks": {
+ "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ }
+ },
+ "disabled-checks": {
+ "description": "Which checks should be disabled.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-checks"
+ },
+ "default": []
+ },
+ "enabled-tags": {
+ "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "disabled-tags": {
+ "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gocritic-tags"
+ }
+ },
+ "settings": {
+ "description": "Settings passed to gocritic. Properties must be valid and enabled check names.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "captLocal": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "paramsOnly" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "commentedOutCode": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minLength" : {
+ "type": "number",
+ "default": 15
+ }
+ }
+ },
+ "elseif": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipBalanced" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "hugeParam": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 80
+ }
+ }
+ },
+ "ifElseChain": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "minThreshold" : {
+ "type": "number",
+ "default": 2
+ }
+ }
+ },
+ "nestingReduce": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bodyWidth" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "rangeExprCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 512
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "rangeValCopy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "sizeThreshold" : {
+ "type": "number",
+ "default": 128
+ },
+ "skipTestFuncs" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "ruleguard": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "debug" : {
+ "type": "string"
+ },
+ "enable" : {
+ "type": "string"
+ },
+ "disable" : {
+ "type": "string"
+ },
+ "failOn" : {
+ "type": "string"
+ },
+ "rules" : {
+ "type": "string"
+ }
+ }
+ },
+ "tooManyResultsChecker": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "maxResults" : {
+ "type": "number",
+ "default": 5
+ }
+ }
+ },
+ "truncateCmp": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipArchDependent" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "underef": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skipRecvDeref" : {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "unnamedResult": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checkExported" : {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "disable-all": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-all": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gocycloSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum code complexity to report (we recommend 10-20).",
+ "type": "integer",
+ "default": 30
+ }
+ }
+ },
+ "godoclintSettings": {
+ "type": "object",
+ "properties": {
+ "default": {
+ "type": "string",
+ "enum": ["all", "basic", "none"],
+ "default": "basic",
+ "description": "Default set of rules to enable."
+ },
+ "enable": {
+ "description": "List of rules to enable in addition to the default set.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "disable": {
+ "description": "List of rules to disable.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/godoclint-rules"
+ }
+ },
+ "options": {
+ "type": "object",
+ "description": "A map for setting individual rule options.",
+ "properties": {
+ "max-len": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer",
+ "description": "Maximum line length for godocs, not including the `//`, `/*` or `*/` tokens.",
+ "default": 77
+ }
+ }
+ },
+ "require-doc": {
+ "type": "object",
+ "properties": {
+ "ignore-exported": {
+ "type": "boolean",
+ "description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
+ "default": false
+ },
+ "ignore-unexported": {
+ "type": "boolean",
+ "description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
+ "default": true
+ }
+ }
+ },
+ "start-with-name": {
+ "type": "object",
+ "properties": {
+ "include-unexported": {
+ "type": "boolean",
+ "description": "Include unexported symbols when applying the `start-with-name` rule.",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "godotSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "scope": {
+ "description": "Comments to be checked.",
+ "enum": ["declarations", "toplevel", "all", "noinline"],
+ "default": "declarations"
+ },
+ "exclude": {
+ "description": "List of regexps for excluding particular comment lines from check.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "period": {
+ "description": "Check that each sentence ends with a period.",
+ "type": "boolean",
+ "default": true
+ },
+ "capital": {
+ "description": "Check that each sentence starts with a capital letter.",
+ "type": "boolean",
+ "default": false
+ },
+ "check-all": {
+ "description": "DEPRECATED: Check all top-level comments, not only declarations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "godoxSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "keywords": {
+ "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["TODO", "BUG", "FIXME"]
+ }
+ }
+ },
+ "gofmtSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simplify": {
+ "description": "Simplify code.",
+ "type": "boolean",
+ "default": true
+ },
+ "rewrite-rules": {
+ "description": "Apply the rewrite rules to the source before reformatting.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "replacement": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "golinesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-len": {
+ "type": "integer",
+ "default": 100
+ },
+ "tab-len": {
+ "type": "integer",
+ "default": 4
+ },
+ "shorten-comments": {
+ "type": "boolean",
+ "default": false
+ },
+ "reformat-tags": {
+ "type": "boolean",
+ "default": true
+ },
+ "chain-split-dots": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "interfacebloatSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max": {
+ "description": "The maximum number of methods allowed for an interface.",
+ "type": "integer"
+ }
+ }
+ },
+ "gofumptSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-rules": {
+ "description": "Choose whether or not to use the extra rules that are disabled by default.",
+ "type": "boolean",
+ "default": false
+ },
+ "module-path": {
+ "description": " Module path which contains the source code being formatted.",
+ "type": "string"
+ }
+ }
+ },
+ "goheaderSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "values": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const": {
+ "description": "Constants to use in the template.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "description": "Value for the constant.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "YEAR": "2030",
+ "COMPANY": "MY FUTURISTIC COMPANY"
+ }
+ ]
+ },
+ "regexp": {
+ "description": "Regular expressions to use in your template.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ "type": "string"
+ }
+ },
+ "examples": [
+ {
+ "AUTHOR": ".*@mycompany\\.com"
+ }
+ ]
+ }
+ }
+ },
+ "template": {
+ "description": "Template to put on top of every file.",
+ "type": "string",
+ "examples": [
+ "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ ]
+ },
+ "template-path": {
+ "description": "Path to the file containing the template source.",
+ "type": "string",
+ "examples": ["my_header_template.txt"]
+ }
+ },
+ "oneOf": [
+ { "required": ["template"] },
+ { "required": ["template-path"] }
+ ]
+ },
+ "goimportsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "local-prefixes": {
+ "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "gomoddirectivesSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "replace-local": {
+ "description": "Allow local `replace` directives.",
+ "type": "boolean",
+ "default": true
+ },
+ "replace-allow-list": {
+ "description": "List of allowed `replace` directives.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retract-allow-no-explanation": {
+ "description": "Allow to not explain why the version has been retracted in the `retract` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "exclude-forbidden": {
+ "description": "Forbid the use of the `exclude` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-forbidden": {
+ "description": "Forbid the use of the `ignore` directives. (>= go1.25)",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-forbidden": {
+ "description": "Forbid the use of the `toolchain` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "toolchain-pattern": {
+ "description": "Defines a pattern to validate `toolchain` directive.",
+ "type": "string"
+ },
+ "tool-forbidden": {
+ "description": "Forbid the use of the `tool` directives.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-debug-forbidden": {
+ "description": "Forbid the use of the `godebug` directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "go-version-pattern": {
+ "description": "Defines a pattern to validate `go` minimum version directive.",
+ "type": "string",
+ "default": ""
+ },
+ "check-module-path": {
+ "description": "Check the validity of the module path.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "gomodguardSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowed": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of allowed modules.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["gopkg.in/yaml.v2"]
+ }
+ },
+ "domains": {
+ "description": "List of allowed module domains.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["golang.org"]
+ }
+ }
+ }
+ },
+ "blocked": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "modules": {
+ "description": "List of blocked modules.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "recommendations": {
+ "description": "Recommended modules that should be used instead.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reason": {
+ "description": "Reason why the recommended module should be used.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "versions": {
+ "description": "List of blocked module version constraints.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "Version constraint.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Reason why the version constraint exists.",
+ "type": "string"
+ }
+ },
+ "required": ["reason"]
+ }
+ }
+ }
+ },
+ "local-replace-directives": {
+ "description": "Raise lint issues if loading local path with replace directive",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ }
+ },
+ "gosecSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "includes": {
+ "type": "array",
+ "description": "To select a subset of rules to run",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "excludes": {
+ "type": "array",
+ "description": "To specify a set of rules to explicitly exclude",
+ "examples": [["G401"]],
+ "items": {
+ "$ref": "#/definitions/gosec-rules"
+ }
+ },
+ "severity": {
+ "description": "Filter out the issues with a lower severity than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "confidence": {
+ "description": "Filter out the issues with a lower confidence than the given value",
+ "type": "string",
+ "enum": ["low", "medium", "high"],
+ "default": "low"
+ },
+ "config": {
+ "description": "To specify the configuration of rules",
+ "type": "object"
+ },
+ "concurrency": {
+ "description": "Concurrency value",
+ "type": "integer"
+ }
+ }
+ },
+ "gosmopolitanSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-time-local": {
+ "description": "Allow and ignore `time.Local` usages.",
+ "type": "boolean",
+ "default": false
+ },
+ "escape-hatches": {
+ "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "watch-for-scripts": {
+ "description": "List of Unicode scripts to watch for any usage in string literals.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "govetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "settings": {
+ "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.",
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/govet-analyzers"
+ },
+ "patternProperties": {
+ "^.*$": {
+ "description": "Run `go tool vet help ` to see all settings.",
+ "type": "object"
+ }
+ }
+ },
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "disable": {
+ "description": "Disable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/govet-analyzers"
+ }
+ },
+ "enable-all": {
+ "description": "Enable all analyzers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all analyzers.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "grouperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "const-require-single-const": {
+ "type": "boolean",
+ "default": false
+ },
+ "const-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-single-import": {
+ "type": "boolean",
+ "default": false
+ },
+ "import-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-single-type": {
+ "type": "boolean",
+ "default": false
+ },
+ "type-require-grouping": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-single-var": {
+ "type": "boolean",
+ "default": false
+ },
+ "var-require-grouping": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ifaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "Enable analyzers by name.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/iface-analyzers"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "unused": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "importasSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "no-unaliased": {
+ "description": "Do not allow unaliased imports of aliased packages.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-extra-aliases": {
+ "description": "Do not allow non-required aliases.",
+ "type": "boolean",
+ "default": false
+ },
+ "alias": {
+ "description": "List of aliases",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pkg": {
+ "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1",
+ "type": "string"
+ },
+ "alias": {
+ "description": "Package alias e.g. autoscalingv1alpha1",
+ "type": "string"
+ }
+ },
+ "required": ["pkg", "alias"]
+ }
+ }
+ }
+ },
+ "inamedparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-single-param": {
+ "description": "Skips check for interface methods with only a single parameter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ineffassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-escaping-errors": {
+ "description": "Check escaping variables of type error, may cause false positives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "iotamixingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-individual": {
+ "description": "Whether to report individual consts rather than just the const block.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "ireturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Use either `reject` or `allow` properties for interfaces matching.",
+ "properties": {
+ "allow": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ },
+ "reject": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "enum": ["anon", "error", "empty", "stdlib"]
+ }
+ ]
+ }
+ }
+ },
+ "anyOf": [
+ {
+ "not": {
+ "properties": {
+ "allow": {
+ "const": "reject"
+ }
+ }
+ },
+ "required": ["allow"]
+ },
+ {
+ "required": ["reject"]
+ }
+ ]
+ },
+ "lllSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "tab-width": {
+ "description": "Width of \"\\t\" in spaces.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 1
+ },
+ "line-length": {
+ "description": "Maximum allowed line length, lines longer will be reported.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 120
+ }
+ }
+ },
+ "maintidxSettings": {
+ "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "under": {
+ "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)",
+ "type": "number",
+ "default": 20
+ }
+ }
+ },
+ "makezeroSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "always": {
+ "description": "Allow only slices initialized with a length of zero.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "loggercheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kitlog": {
+ "description": "Allow check for the github.com/go-kit/log library.",
+ "type": "boolean",
+ "default": true
+ },
+ "klog": {
+ "description": "Allow check for the k8s.io/klog/v2 library.",
+ "type": "boolean",
+ "default": true
+ },
+ "logr": {
+ "description": "Allow check for the github.com/go-logr/logr library.",
+ "type": "boolean",
+ "default": true
+ },
+ "slog": {
+ "description": "Allow check for the log/slog library.",
+ "type": "boolean",
+ "default": true
+ },
+ "zap": {
+ "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-string-key": {
+ "description": "Require all logging keys to be inlined constant strings.",
+ "type": "boolean",
+ "default": false
+ },
+ "no-printf-like": {
+ "description": "Require printf-like format specifier (%s, %d for example) not present.",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "misspellSettings": {
+ "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "enum": ["US", "UK"]
+ },
+ "ignore-rules": {
+ "description": "List of rules to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mode": {
+ "description": "Mode of the analysis.",
+ "enum": ["restricted", "", "default"],
+ "default": ""
+ },
+ "extra-words": {
+ "description": "Extra word corrections.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "correction": {
+ "type": "string"
+ },
+ "typo": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "musttagSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "functions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "arg-pos": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "nakedretSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-func-lines": {
+ "description": "Report if a function has more lines of code than this value and it has naked returns.",
+ "type": "integer",
+ "minimum": 0,
+ "default": 30
+ }
+ }
+ },
+ "nestifSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "min-complexity": {
+ "description": "Minimum complexity of \"if\" statements to report.",
+ "type": "integer",
+ "default": 5
+ }
+ }
+ },
+ "nilnilSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only-two": {
+ "type": "boolean",
+ "description": "To check functions with only two return values.",
+ "default": true
+ },
+ "detect-opposite": {
+ "type": "boolean",
+ "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).",
+ "default": false
+ },
+ "checked-types": {
+ "type": "array",
+ "description": "List of return types to check.",
+ "items": {
+ "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ },
+ "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"]
+ }
+ }
+ },
+ "nlreturnSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "block-size": {
+ "description": "set block size that is still ok",
+ "type": "number",
+ "default": 0,
+ "minimum": 0
+ }
+ }
+ },
+ "mndSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignored-files": {
+ "description": "List of file patterns to exclude from analysis.",
+ "examples": [["magic1_.*.go"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Comma-separated list of function patterns to exclude from the analysis.",
+ "examples": [["math.*", "http.StatusText", "make"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-numbers": {
+ "description": "List of numbers to exclude from analysis.",
+ "examples": [["1000", "1234_567_890", "3.14159264"]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "checks": {
+ "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "argument",
+ "case",
+ "condition",
+ "operation",
+ "return",
+ "assign"
+ ]
+ }
+ }
+ }
+ },
+ "modernizeSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable": {
+ "description": "List of analyzers to disable.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/modernize-analyzers"
+ }
+ }
+ }
+ },
+ "nolintlintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-unused": {
+ "description": "Enable to ensure that nolint directives are all used.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-no-explanation": {
+ "description": "Exclude these linters from requiring an explanation.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ },
+ "default": []
+ },
+ "require-explanation": {
+ "description": "Enable to require an explanation of nonzero length after each nolint directive.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-specific": {
+ "description": "Enable to require nolint directives to mention the specific linter being suppressed.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reassignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "recvcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "disable-builtin": {
+ "description": "Disables the built-in method exclusions.",
+ "type": "boolean",
+ "default": true
+ },
+ "exclusions": {
+ "description": "User-defined method exclusions.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "nonamedreturnsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "report-error-in-defer": {
+ "description": "Report named error if it is assigned inside defer.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "paralleltestSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-missing": {
+ "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignore-missing-subtests": {
+ "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "perfsprintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "integer-format": {
+ "description": "Enable/disable optimization of integer formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "int-conversion": {
+ "description": "Optimizes even if it requires an int or uint type cast.",
+ "type": "boolean",
+ "default": true
+ },
+ "error-format": {
+ "description": "Enable/disable optimization of error formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "err-error": {
+ "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.",
+ "type": "boolean",
+ "default": false
+ },
+ "errorf": {
+ "description": "Optimizes `fmt.Errorf`.",
+ "type": "boolean",
+ "default": true
+ },
+ "string-format": {
+ "description": "Enable/disable optimization of string formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "sprintf1": {
+ "description": "Optimizes `fmt.Sprintf` with only one argument.",
+ "type": "boolean",
+ "default": true
+ },
+ "strconcat": {
+ "description": "Optimizes into strings concatenation.",
+ "type": "boolean",
+ "default": true
+ },
+ "bool-format": {
+ "description": "Enable/disable optimization of bool formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "hex-format": {
+ "description": "Enable/disable optimization of hex formatting.",
+ "type": "boolean",
+ "default": true
+ },
+ "concat-loop": {
+ "description": "Enable/disable optimization of concat loop.",
+ "type": "boolean",
+ "default": true
+ },
+ "loop-other-ops": {
+ "description": "Optimization of `concat-loop` even with other operations.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "preallocSettings": {
+ "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "simple": {
+ "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.",
+ "type": "boolean",
+ "default": true
+ },
+ "range-loops": {
+ "description": "Report preallocation suggestions on range loops.",
+ "type": "boolean",
+ "default": true
+ },
+ "for-loops": {
+ "description": "Report preallocation suggestions on for loops.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "predeclaredSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore": {
+ "description": "List of predeclared identifiers to not report on.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "qualified-name": {
+ "description": "Include method names and field names in checks.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "promlinterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "strict": {},
+ "disabled-linters": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "Help",
+ "MetricUnits",
+ "Counter",
+ "HistogramSummaryReserved",
+ "MetricTypeInName",
+ "ReservedChars",
+ "CamelCase",
+ "UnitAbbreviations"
+ ]
+ }
+ }
+ }
+ },
+ "protogetterSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-generated-by": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["protoc-gen-go-my-own-generator"]
+ }
+ },
+ "skip-files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["*.pb.go"]
+ }
+ },
+ "skip-any-generated": {
+ "description": "Skip any generated files from the checking.",
+ "type": "boolean",
+ "default": false
+ },
+ "replace-first-arg-in-append": {
+ "description": "Skip first argument of append function.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "reviveSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "examples": [
+ {
+ "ignore-generated-header": true,
+ "severity": "warning",
+ "rules": [
+ {
+ "name": "indent-error-flow",
+ "severity": "warning"
+ },
+ {
+ "name": "add-constant",
+ "severity": "warning",
+ "arguments": [
+ {
+ "maxLitCount": "3",
+ "allowStrs": "\"\"",
+ "allowInts": "0,1,2",
+ "allowFloats": "0.0,0.,1.0,1.,2.0,2."
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "max-open-files": {
+ "type": "integer"
+ },
+ "confidence": {
+ "type": "number"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "enable-all-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "enable-default-rules": {
+ "type": "boolean",
+ "default": false
+ },
+ "directives": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": ["specify-disable-reason"]
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/revive-rules",
+ "title": "The rule name"
+ },
+ "disabled": {
+ "type": "boolean"
+ },
+ "severity": {
+ "type": "string",
+ "enum": ["warning", "error"]
+ },
+ "exclude": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "arguments": {
+ "type": "array"
+ }
+ }
+ }
+ }
+ }
+ },
+ "rowserrcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": {
+ "description": "",
+ "type": "string",
+ "examples": ["github.com/jmoiron/sqlx"]
+ }
+ }
+ }
+ },
+ "sloglintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "kv-only": {
+ "description": "Enforce using key-value pairs only (incompatible with attr-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-global": {
+ "description": "Enforce not using global loggers.",
+ "enum": ["", "all", "default"],
+ "default": ""
+ },
+ "no-mixed-args": {
+ "description": "Enforce not mixing key-value pairs and attributes.",
+ "type": "boolean",
+ "default": true
+ },
+ "context": {
+ "description": "Enforce using methods that accept a context.",
+ "enum": ["", "all", "scope"],
+ "default": ""
+ },
+ "static-msg": {
+ "description": "Enforce using static values for log messages.",
+ "type": "boolean",
+ "default": false
+ },
+ "msg-style": {
+ "description": "Enforce message style.",
+ "enum": ["", "lowercased", "capitalized"],
+ "default": ""
+ },
+ "key-naming-case": {
+ "description": "Enforce a single key naming convention.",
+ "enum": ["snake", "kebab", "camel", "pascal"]
+ },
+ "attr-only": {
+ "description": "Enforce using attributes only (incompatible with kv-only).",
+ "type": "boolean",
+ "default": false
+ },
+ "no-raw-keys": {
+ "description": "Enforce using constants instead of raw keys.",
+ "type": "boolean",
+ "default": false
+ },
+ "forbidden-keys": {
+ "description": "Enforce not using specific keys.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "args-on-sep-lines": {
+ "description": "Enforce putting arguments on separate lines.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spancheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "description": "Checks to enable.",
+ "type": "array",
+ "items": {
+ "enum": ["end", "record-error", "set-status"]
+ }
+ },
+ "ignore-check-signatures": {
+ "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "extra-start-span-signatures": {
+ "description": "A list of regexes for additional function signatures that create spans.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "staticcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "checks": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/staticcheck-checks"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "dot-import-whitelist": {
+ "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "http-status-code-whitelist": {
+ "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.",
+ "default": ["200", "400", "404", "500"],
+ "type": "array",
+ "items": {
+ "enum": [
+ "100",
+ "101",
+ "102",
+ "103",
+ "200",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "207",
+ "208",
+ "226",
+ "300",
+ "301",
+ "302",
+ "303",
+ "304",
+ "305",
+ "306",
+ "307",
+ "308",
+ "400",
+ "401",
+ "402",
+ "403",
+ "404",
+ "405",
+ "406",
+ "407",
+ "408",
+ "409",
+ "410",
+ "411",
+ "412",
+ "413",
+ "414",
+ "415",
+ "416",
+ "417",
+ "418",
+ "421",
+ "422",
+ "423",
+ "424",
+ "425",
+ "426",
+ "428",
+ "429",
+ "431",
+ "451",
+ "500",
+ "501",
+ "502",
+ "503",
+ "504",
+ "505",
+ "506",
+ "507",
+ "508",
+ "510",
+ "511"
+ ]
+ }
+ },
+ "initialisms": {
+ "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "default": [
+ "ACL",
+ "API",
+ "ASCII",
+ "CPU",
+ "CSS",
+ "DNS",
+ "EOF",
+ "GUID",
+ "HTML",
+ "HTTP",
+ "HTTPS",
+ "ID",
+ "IP",
+ "JSON",
+ "QPS",
+ "RAM",
+ "RPC",
+ "SLA",
+ "SMTP",
+ "SQL",
+ "SSH",
+ "TCP",
+ "TLS",
+ "TTL",
+ "UDP",
+ "UI",
+ "GID",
+ "UID",
+ "UUID",
+ "URI",
+ "URL",
+ "UTF8",
+ "VM",
+ "XML",
+ "XMPP",
+ "XSRF",
+ "XSS",
+ "SIP",
+ "RTP",
+ "AMQP",
+ "DB",
+ "TS"
+ ]
+ }
+ }
+ }
+ },
+ "tagalignSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "align": {
+ "description": "Align and sort can be used together or separately.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort": {
+ "description": "Whether enable tags sort.",
+ "type": "boolean",
+ "default": true
+ },
+ "order": {
+ "description": "Specify the order of tags, the other tags will be sorted by name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "json",
+ "yaml",
+ "yml",
+ "toml",
+ "mapstructure",
+ "binding",
+ "validate"
+ ]
+ ]
+ },
+ "strict": {
+ "description": "Whether enable strict style.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "tagliatelleSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "case": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "overrides": {
+ "description": "Overrides the default/root configuration.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pkg"],
+ "properties": {
+ "pkg": {
+ "description": "A package path.",
+ "type": "string"
+ },
+ "use-field-name": {
+ "description": "Use the struct field name to check the name of the struct tag.",
+ "type": "boolean",
+ "default": false
+ },
+ "ignored-fields": {
+ "description": "The field names to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ },
+ "ignore": {
+ "description": "Ignore the package (takes precedence over all other configurations).",
+ "type": "boolean",
+ "default": false
+ },
+ "rules": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ }
+ }
+ },
+ "extended-rules": {
+ "description": "Defines the association between tag name and case.",
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["case"],
+ "properties": {
+ "case": {
+ "$ref": "#/definitions/tagliatelle-cases"
+ },
+ "extra-initialisms": {
+ "type": "boolean",
+ "default": false
+ },
+ "initialism-overrides": {
+ "type": "object",
+ "patternProperties": {
+ "^.+$": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "testifylintSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable-all": {
+ "description": "Enable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "disable-all": {
+ "description": "Disable all checkers.",
+ "type": "boolean",
+ "default": false
+ },
+ "enable": {
+ "description": "Enable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ]
+ },
+ "default": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "useless-assert"
+ ]
+ },
+ "disable": {
+ "description": "Disable specific checkers.",
+ "type": "array",
+ "items": {
+ "enum": [
+ "blank-import",
+ "bool-compare",
+ "compares",
+ "contains",
+ "empty",
+ "encoded-compare",
+ "equal-values",
+ "error-is-as",
+ "error-nil",
+ "expected-actual",
+ "float-compare",
+ "formatter",
+ "go-require",
+ "len",
+ "negative-positive",
+ "nil-compare",
+ "regexp",
+ "require-error",
+ "suite-broken-parallel",
+ "suite-dont-use-pkg",
+ "suite-extra-assert-call",
+ "suite-method-signature",
+ "suite-subtest-run",
+ "suite-thelper",
+ "useless-assert"
+ ],
+ "default": [
+ "suite-thelper"
+ ]
+ }
+ },
+ "bool-compare": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-custom-types": {
+ "description": "To ignore user defined types (over builtin bool).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "expected-actual": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "description": "Regexp for expected variable name.",
+ "type": "string",
+ "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)"
+ }
+ }
+ },
+ "formatter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-format-string": {
+ "description": "To enable go vet's printf checks.",
+ "type": "boolean",
+ "default": true
+ },
+ "require-f-funcs": {
+ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.",
+ "type": "boolean",
+ "default": false
+ },
+ "require-string-msg": {
+ "description": "To require that the first element of msgAndArgs (msg) has a string type.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "go-require": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ignore-http-handlers": {
+ "description": "To ignore HTTP handlers (like http.HandlerFunc).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "require-error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fn-pattern": {
+ "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
+ "suite-extra-assert-call": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "description": "To require or remove extra Assert() call?",
+ "type": "string",
+ "enum": ["remove", "require"],
+ "default": "remove"
+ }
+ }
+ }
+ }
+ },
+ "testpackageSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "skip-regexp": {
+ "description": "Files with names matching this regular expression are skipped.",
+ "type": "string",
+ "examples": ["(export|internal)_test\\.go"]
+ },
+ "allow-packages": {
+ "description": "List of packages that don't end with _test that tests are allowed to be in.",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "examples": ["example"]
+ }
+ }
+ }
+ },
+ "thelperSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "test": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `t.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.T is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.T param has t name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "benchmark": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `b.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.B is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.B param has b name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "tb": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `tb.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.TB is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.TB param has tb name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ },
+ "fuzz": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "begin": {
+ "description": "Check if `f.Helper()` begins helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "first": {
+ "description": "Check if *testing.F is first param of helper function.",
+ "default": true,
+ "type": "boolean"
+ },
+ "name": {
+ "description": "Check if *testing.F param has f name.",
+ "default": true,
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "usestdlibvarsSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "http-method": {
+ "description": "Suggest the use of http.MethodXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "http-status-code": {
+ "description": "Suggest the use of http.StatusXX.",
+ "type": "boolean",
+ "default": true
+ },
+ "time-weekday": {
+ "description": "Suggest the use of time.Weekday.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-month": {
+ "description": "Suggest the use of time.Month.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "time-layout": {
+ "description": "Suggest the use of time.Layout.",
+ "type": "boolean",
+ "default": false
+ },
+ "time-date-month": {
+ "description": "Suggest the use of time.Month in time.Date.",
+ "type": "boolean",
+ "default": false
+ },
+ "crypto-hash": {
+ "description": "Suggest the use of crypto.Hash.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "default-rpc-path": {
+ "description": "Suggest the use of rpc.DefaultXXPath.",
+ "type": "boolean",
+ "default": false
+ },
+ "sql-isolation-level": {
+ "description": "Suggest the use of sql.LevelXX.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "tls-signature-scheme": {
+ "description": "Suggest the use of tls.SignatureScheme.String().",
+ "type": "boolean",
+ "default": false
+ },
+ "constant-kind": {
+ "description": "Suggest the use of constant.Kind.String().",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "usetestingSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "context-background": {
+ "type": "boolean",
+ "default": false
+ },
+ "context-todo": {
+ "type": "boolean",
+ "default": false
+ },
+ "os-chdir": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-mkdir-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-setenv": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-create-temp": {
+ "type": "boolean",
+ "default": true
+ },
+ "os-temp-dir": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unconvertSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast-math": {
+ "type": "boolean",
+ "default": false
+ },
+ "safe": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unparamSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-exported": {
+ "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "unqueryvetSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-sql-builders": {
+ "description": "Enable SQL builder checking.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-aliased-wildcard": {
+ "description": "Enable aliased wildcard detection like SELECT t.*.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-concat": {
+ "description": "Enable string concatenation analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-format-strings": {
+ "description": "Enable format string analysis like fmt.Sprintf.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-string-builder": {
+ "description": "Enable strings.Builder analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-subqueries": {
+ "description": "Enable subquery analysis.",
+ "type": "boolean",
+ "default": true
+ },
+ "check-n1": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-sql-injection": {
+ "type": "boolean",
+ "default": false
+ },
+ "check-tx-leaks": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowed-patterns": {
+ "description": "Regex patterns for acceptable SELECT * usage.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow": {
+ "description": "Allow is a list of SQL patterns to allow (whitelist).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignored-functions": {
+ "description": "Functions to ignore.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sql-builders": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "squirrel": {
+ "type": "boolean",
+ "default": true
+ },
+ "gorm": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlx": {
+ "type": "boolean",
+ "default": true
+ },
+ "ent": {
+ "type": "boolean",
+ "default": true
+ },
+ "pgx": {
+ "type": "boolean",
+ "default": true
+ },
+ "bun": {
+ "type": "boolean",
+ "default": true
+ },
+ "sqlboiler": {
+ "type": "boolean",
+ "default": true
+ },
+ "jet": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "custom-rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "pattern": {
+ "type": "string"
+ },
+ "patterns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "when": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "unusedSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field-writes-are-uses": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "post-statements-are-reads": {
+ "description": "",
+ "type": "boolean",
+ "default": false
+ },
+ "exported-fields-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "parameters-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "local-variables-are-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ },
+ "generated-is-used": {
+ "description": "",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "varnamelenSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-distance": {
+ "description": "Variables used in at most this N-many lines will be ignored.",
+ "type": "integer",
+ "default": 5
+ },
+ "min-name-length": {
+ "description": "The minimum length of a variable's name that is considered `long`.",
+ "type": "integer",
+ "default": 3
+ },
+ "check-receiver": {
+ "description": "Check method receiver names.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-return": {
+ "description": "Check named return values.",
+ "default": false,
+ "type": "boolean"
+ },
+ "check-type-param": {
+ "description": "Check type parameters.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-type-assert-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a type assertion",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-map-index-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a map index.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-chan-recv-ok": {
+ "description": "Ignore `ok` variables that hold the bool return value of a channel receive.",
+ "default": false,
+ "type": "boolean"
+ },
+ "ignore-names": {
+ "description": "Optional list of variable names that should be ignored completely.",
+ "default": [[]],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-decls": {
+ "description": "Optional list of variable declarations that should be ignored completely.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"]
+ ]
+ }
+ }
+ },
+ "whitespaceSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "multi-if": {
+ "description": "Enforces newlines (or comments) after every multi-line if statement",
+ "type": "boolean",
+ "default": false
+ },
+ "multi-func": {
+ "description": "Enforces newlines (or comments) after every multi-line function signature",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wrapcheckSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "extra-ignore-sigs": {
+ "description": "An array of strings specifying additional substrings of signatures to ignore.",
+ "default": [
+ ".CustomError(",
+ ".SpecificWrap("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sigs": {
+ "description": "An array of strings which specify substrings of signatures to ignore.",
+ "default": [
+ ".Errorf(",
+ "errors.New(",
+ "errors.Unwrap(",
+ ".Wrap(",
+ ".Wrapf(",
+ ".WithMessage(",
+ ".WithMessagef(",
+ ".WithStack("
+ ],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-sig-regexps": {
+ "description": "An array of strings which specify regular expressions of signatures to ignore.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-package-globs": {
+ "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ignore-interface-regexps": {
+ "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.",
+ "default": [""],
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "report-internal-errors": {
+ "description": "Determines whether wrapcheck should report errors returned from inside the package.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "wslSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-assign-and-anything": {
+ "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-assign-and-call": {
+ "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-cuddle-declarations": {
+ "description": "Allow declarations (var) to be cuddled.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-cuddle-with-calls": {
+ "description": "A list of call idents that everything can be cuddled with.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-with-rhs": {
+ "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow-cuddle-used-in-block": {
+ "description": "Allow cuddling with any block as long as the variable is used somewhere in the block",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-multiline-assign": {
+ "description": "Allow multiline assignments to be cuddled.",
+ "type": "boolean",
+ "default": true
+ },
+ "allow-separated-leading-comment": {
+ "description": "Allow leading comments to be separated with empty lines.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-trailing-comment": {
+ "description": "Allow trailing comments in ending of blocks.",
+ "type": "boolean",
+ "default": false
+ },
+ "error-variable-names": {
+ "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "force-case-trailing-whitespace": {
+ "description": "Force newlines in end of case at this limit (0 = never).",
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "force-err-cuddling": {
+ "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.",
+ "type": "boolean",
+ "default": false
+ },
+ "force-short-decl-cuddling": {
+ "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.",
+ "type": "boolean",
+ "default": false
+ },
+ "strict-append": {
+ "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "wslSettingsV5": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allow-first-in-block": {
+ "type": "boolean",
+ "default": true
+ },
+ "allow-whole-block": {
+ "type": "boolean",
+ "default": false
+ },
+ "branch-max-lines": {
+ "type": "integer",
+ "default": 2
+ },
+ "case-max-lines": {
+ "type": "integer",
+ "default": 0
+ },
+ "default": {
+ "enum": ["all", "none", "default", ""],
+ "default": "default"
+ },
+ "enable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ },
+ "disable": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/wsl-checks"
+ }
+ }
+ }
+ },
+ "copyloopvarSettings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "check-alias": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "customSettings": {
+ "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.",
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "description": "The plugin type.",
+ "enum": ["module", "goplugin"],
+ "default": "goplugin"
+ },
+ "path": {
+ "description": "The path to the plugin *.so. Can be absolute or local.",
+ "type": "string",
+ "examples": ["/path/to/example.so"]
+ },
+ "description": {
+ "description": "The description of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "original-url": {
+ "description": "Intended to point to the repo location of the linter, for documentation purposes only.",
+ "type": "string"
+ },
+ "settings": {
+ "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.",
+ "type": "object"
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {"enum": ["module"] }
+ },
+ "required": ["type"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["version"],
+ "properties": {
+ "version": {
+ "type": "string",
+ "default": "2"
+ },
+ "run": {
+ "description": "Options for analysis running,",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "concurrency": {
+ "description": "Number of concurrent runners. Defaults to the number of available CPU cores.",
+ "type": "integer",
+ "minimum": 0,
+ "examples": [4]
+ },
+ "timeout": {
+ "description": "Timeout for the analysis.",
+ "type": "string",
+ "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$",
+ "default": "1m",
+ "examples": ["30s", "5m", "5m30s"]
+ },
+ "issues-exit-code": {
+ "description": "Exit code when at least one issue was found.",
+ "type": "integer",
+ "default": 1
+ },
+ "tests": {
+ "description": "Enable inclusion of test files.",
+ "type": "boolean",
+ "default": true
+ },
+ "build-tags": {
+ "description": "List of build tags to pass to all linters.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [["mytag"]]
+ },
+ "modules-download-mode": {
+ "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
+ "enum": ["mod", "readonly", "vendor"]
+ },
+ "enable-build-vcs": {
+ "type": "boolean",
+ "default": false
+ },
+ "allow-parallel-runners": {
+ "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.",
+ "type": "boolean",
+ "default": false
+ },
+ "allow-serial-runners": {
+ "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.",
+ "type": "boolean",
+ "default": false
+ },
+ "go": {
+ "description": "Targeted Go version.",
+ "type": "string",
+ "default": "1.17"
+ },
+ "relative-path-mode": {
+ "description": "The mode used to evaluate relative paths.",
+ "type": "string",
+ "$ref": "#/definitions/relative-path-modes",
+ "default": "wd"
+ }
+ }
+ },
+ "output": {
+ "description": "Output configuration options.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "formats": {
+ "description": "Output formats to use.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "print-issued-lines": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "json": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "tab": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "print-linter-name": {
+ "type": "boolean",
+ "default": true
+ },
+ "colors": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "html": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "checkstyle": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "code-climate": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "junit-xml": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "$ref": "#/definitions/formats-path",
+ "default": "stdout"
+ },
+ "extended": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "teamcity": {
+ "$ref": "#/definitions/simple-format"
+ },
+ "sarif": {
+ "$ref": "#/definitions/simple-format"
+ }
+ }
+ },
+ "path-mode": {
+ "type": "string",
+ "default": "",
+ "examples": ["abs"]
+ },
+ "path-prefix": {
+ "description": "Add a prefix to the output file references.",
+ "type": "string",
+ "default": ""
+ },
+ "show-stats": {
+ "description": "Show statistics per linter.",
+ "type": "boolean",
+ "default": true
+ },
+ "sort-order": {
+ "type": "array",
+ "items": {
+ "enum": ["linter", "severity", "file"]
+ }
+ }
+ }
+ },
+ "linters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "enum": [
+ "standard",
+ "all",
+ "none",
+ "fast"
+ ]
+ },
+ "enable": {
+ "description": "List of enabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "disable": {
+ "description": "List of disabled linters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "settings": {
+ "description": "All available settings of specific linters.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "dupword": {
+ "$ref": "#/definitions/settings/definitions/dupwordSettings"
+ },
+ "asasalint": {
+ "$ref": "#/definitions/settings/definitions/asasalintSettings"
+ },
+ "bidichk": {
+ "$ref": "#/definitions/settings/definitions/bidichkSettings"
+ },
+ "cyclop": {
+ "$ref": "#/definitions/settings/definitions/cyclopSettings"
+ },
+ "decorder": {
+ "$ref": "#/definitions/settings/definitions/decorderSettings"
+ },
+ "depguard":{
+ "$ref": "#/definitions/settings/definitions/depguardSettings"
+ },
+ "dogsled": {
+ "$ref": "#/definitions/settings/definitions/dogsledSettings"
+ },
+ "dupl": {
+ "$ref": "#/definitions/settings/definitions/duplSettings"
+ },
+ "embeddedstructfieldcheck": {
+ "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings"
+ },
+ "errcheck": {
+ "$ref": "#/definitions/settings/definitions/errcheckSettings"
+ },
+ "errchkjson": {
+ "$ref": "#/definitions/settings/definitions/errchkjsonSettings"
+ },
+ "errorlint": {
+ "$ref": "#/definitions/settings/definitions/errorlintSettings"
+ },
+ "exhaustive": {
+ "$ref": "#/definitions/settings/definitions/exhaustiveSettings"
+ },
+ "exhaustruct": {
+ "$ref": "#/definitions/settings/definitions/exhaustructSettings"
+ },
+ "fatcontext": {
+ "$ref": "#/definitions/settings/definitions/fatcontextSettings"
+ },
+ "forbidigo": {
+ "$ref": "#/definitions/settings/definitions/forbidigoSettings"
+ },
+ "funcorder": {
+ "$ref": "#/definitions/settings/definitions/funcorderSettings"
+ },
+ "funlen": {
+ "$ref": "#/definitions/settings/definitions/funlenSettings"
+ },
+ "ginkgolinter": {
+ "$ref": "#/definitions/settings/definitions/ginkgolinterSettings"
+ },
+ "gochecksumtype": {
+ "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings"
+ },
+ "gocognit": {
+ "$ref": "#/definitions/settings/definitions/gocognitSettings"
+ },
+ "goconst": {
+ "$ref": "#/definitions/settings/definitions/goconstSettings"
+ },
+ "gocritic": {
+ "$ref": "#/definitions/settings/definitions/gocriticSettings"
+ },
+ "gocyclo": {
+ "$ref": "#/definitions/settings/definitions/gocycloSettings"
+ },
+ "godoclint": {
+ "$ref": "#/definitions/settings/definitions/godoclintSettings"
+ },
+ "godot": {
+ "$ref": "#/definitions/settings/definitions/godotSettings"
+ },
+ "godox": {
+ "$ref": "#/definitions/settings/definitions/godoxSettings"
+ },
+ "interfacebloat":{
+ "$ref": "#/definitions/settings/definitions/interfacebloatSettings"
+ },
+ "goheader": {
+ "$ref": "#/definitions/settings/definitions/goheaderSettings"
+ },
+ "gomoddirectives": {
+ "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
+ },
+ "gomodguard": {
+ "$ref": "#/definitions/settings/definitions/gomodguardSettings"
+ },
+ "gosec": {
+ "$ref": "#/definitions/settings/definitions/gosecSettings"
+ },
+ "gosmopolitan": {
+ "$ref": "#/definitions/settings/definitions/gosmopolitanSettings"
+ },
+ "govet": {
+ "$ref": "#/definitions/settings/definitions/govetSettings"
+ },
+ "grouper": {
+ "$ref": "#/definitions/settings/definitions/grouperSettings"
+ },
+ "iface": {
+ "$ref": "#/definitions/settings/definitions/ifaceSettings"
+ },
+ "importas": {
+ "$ref": "#/definitions/settings/definitions/importasSettings"
+ },
+ "inamedparam": {
+ "$ref": "#/definitions/settings/definitions/inamedparamSettings"
+ },
+ "ineffassign": {
+ "$ref": "#/definitions/settings/definitions/ineffassignSettings"
+ },
+ "iotamixing": {
+ "$ref": "#/definitions/settings/definitions/iotamixingSettings"
+ },
+ "ireturn": {
+ "$ref": "#/definitions/settings/definitions/ireturnSettings"
+ },
+ "lll": {
+ "$ref": "#/definitions/settings/definitions/lllSettings"
+ },
+ "maintidx": {
+ "$ref": "#/definitions/settings/definitions/maintidxSettings"
+ },
+ "makezero":{
+ "$ref": "#/definitions/settings/definitions/makezeroSettings"
+ },
+ "loggercheck": {
+ "$ref": "#/definitions/settings/definitions/loggercheckSettings"
+ },
+ "misspell": {
+ "$ref": "#/definitions/settings/definitions/misspellSettings"
+ },
+ "musttag": {
+ "$ref": "#/definitions/settings/definitions/musttagSettings"
+ },
+ "nakedret": {
+ "$ref": "#/definitions/settings/definitions/nakedretSettings"
+ },
+ "nestif": {
+ "$ref": "#/definitions/settings/definitions/nestifSettings"
+ },
+ "nilnil": {
+ "$ref": "#/definitions/settings/definitions/nilnilSettings"
+ },
+ "nlreturn": {
+ "$ref": "#/definitions/settings/definitions/nlreturnSettings"
+ },
+ "mnd": {
+ "$ref": "#/definitions/settings/definitions/mndSettings"
+ },
+ "modernize": {
+ "$ref": "#/definitions/settings/definitions/modernizeSettings"
+ },
+ "nolintlint":{
+ "$ref": "#/definitions/settings/definitions/nolintlintSettings"
+ },
+ "reassign": {
+ "$ref": "#/definitions/settings/definitions/reassignSettings"
+ },
+ "recvcheck": {
+ "$ref": "#/definitions/settings/definitions/recvcheckSettings"
+ },
+ "nonamedreturns": {
+ "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings"
+ },
+ "paralleltest": {
+ "$ref": "#/definitions/settings/definitions/paralleltestSettings"
+ },
+ "perfsprint": {
+ "$ref": "#/definitions/settings/definitions/perfsprintSettings"
+ },
+ "prealloc": {
+ "$ref": "#/definitions/settings/definitions/preallocSettings"
+ },
+ "predeclared": {
+ "$ref": "#/definitions/settings/definitions/predeclaredSettings"
+ },
+ "promlinter": {
+ "$ref": "#/definitions/settings/definitions/promlinterSettings"
+ },
+ "protogetter": {
+ "$ref": "#/definitions/settings/definitions/protogetterSettings"
+ },
+ "revive": {
+ "$ref": "#/definitions/settings/definitions/reviveSettings"
+ },
+ "rowserrcheck": {
+ "$ref": "#/definitions/settings/definitions/rowserrcheckSettings"
+ },
+ "sloglint": {
+ "$ref": "#/definitions/settings/definitions/sloglintSettings"
+ },
+ "spancheck": {
+ "$ref": "#/definitions/settings/definitions/spancheckSettings"
+ },
+ "staticcheck":{
+ "$ref": "#/definitions/settings/definitions/staticcheckSettings"
+ },
+ "tagalign": {
+ "$ref": "#/definitions/settings/definitions/tagalignSettings"
+ },
+ "tagliatelle": {
+ "$ref": "#/definitions/settings/definitions/tagliatelleSettings"
+ },
+ "testifylint": {
+ "$ref": "#/definitions/settings/definitions/testifylintSettings"
+ },
+ "testpackage": {
+ "$ref": "#/definitions/settings/definitions/testpackageSettings"
+ },
+ "thelper": {
+ "$ref": "#/definitions/settings/definitions/thelperSettings"
+ },
+ "usestdlibvars": {
+ "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings"
+ },
+ "usetesting": {
+ "$ref": "#/definitions/settings/definitions/usetestingSettings"
+ },
+ "unconvert": {
+ "$ref": "#/definitions/settings/definitions/unconvertSettings"
+ },
+ "unparam": {
+ "$ref": "#/definitions/settings/definitions/unparamSettings"
+ },
+ "unqueryvet": {
+ "$ref": "#/definitions/settings/definitions/unqueryvetSettings"
+ },
+ "unused": {
+ "$ref": "#/definitions/settings/definitions/unusedSettings"
+ },
+ "varnamelen": {
+ "$ref": "#/definitions/settings/definitions/varnamelenSettings"
+ },
+ "whitespace": {
+ "$ref": "#/definitions/settings/definitions/whitespaceSettings"
+ },
+ "wrapcheck": {
+ "$ref": "#/definitions/settings/definitions/wrapcheckSettings"
+ },
+ "wsl": {
+ "$ref": "#/definitions/settings/definitions/wslSettings"
+ },
+ "wsl_v5": {
+ "$ref": "#/definitions/settings/definitions/wslSettingsV5"
+ },
+ "copyloopvar": {
+ "$ref": "#/definitions/settings/definitions/copyloopvarSettings"
+ },
+ "custom":{
+ "$ref": "#/definitions/settings/definitions/customSettings"
+ }
+ }
+ },
+ "exclusions":{
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ },
+ "presets": {
+ "type": "array",
+ "items": {
+ "enum": [
+ "comments",
+ "std-error-handling",
+ "common-false-positives",
+ "legacy"
+ ]
+ }
+ },
+ "rules": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths-except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "formatters": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enable": {
+ "description": "List of enabled formatters.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/formatter-names"
+ }
+ },
+ "settings": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "gci": {
+ "$ref": "#/definitions/settings/definitions/gciSettings"
+ },
+ "gofmt": {
+ "$ref": "#/definitions/settings/definitions/gofmtSettings"
+ },
+ "gofumpt": {
+ "$ref": "#/definitions/settings/definitions/gofumptSettings"
+ },
+ "goimports": {
+ "$ref": "#/definitions/settings/definitions/goimportsSettings"
+ },
+ "golines": {
+ "$ref": "#/definitions/settings/definitions/golinesSettings"
+ }
+ }
+ },
+ "exclusions": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "generated": {
+ "enum": ["strict", "lax", "disable"],
+ "default": "strict"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "warn-unused": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ }
+ },
+ "issues": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "max-issues-per-linter": {
+ "description": "Maximum issues count per one linter. Set to 0 to disable.",
+ "type": "integer",
+ "default": 50,
+ "minimum": 0
+ },
+ "max-same-issues": {
+ "description": "Maximum count of issues with the same text. Set to 0 to disable.",
+ "type": "integer",
+ "default": 3,
+ "minimum": 0
+ },
+ "new": {
+ "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.",
+ "type": "boolean",
+ "default": false
+ },
+ "new-from-merge-base": {
+ "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).",
+ "type": "string"
+ },
+ "new-from-rev": {
+ "description": "Show only new issues created after this git revision.",
+ "type": "string"
+ },
+ "new-from-patch": {
+ "description": "Show only new issues created in git patch with this file path.",
+ "type": "string",
+ "examples": ["path/to/patch/file"]
+ },
+ "fix": {
+ "description": "Apply the fixes detected by the linters and formatters (if it's supported by the linter).",
+ "type": "boolean",
+ "default": false
+ },
+ "uniq-by-line": {
+ "description": "Make issues output unique by line.",
+ "type": "boolean",
+ "default": true
+ },
+ "whole-files": {
+ "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "severity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "default": {
+ "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.",
+ "type": "string",
+ "default": ""
+ },
+ "rules": {
+ "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "severity": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ },
+ "path-except": {
+ "type": "string"
+ },
+ "linters": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/linter-names"
+ }
+ },
+ "text": {
+ "type": "string"
+ },
+ "source": {
+ "type": "string"
+ }
+ },
+ "required": ["severity"],
+ "anyOf": [
+ { "required": ["path"] },
+ { "required": ["path-except"] },
+ { "required": ["linters"] },
+ { "required": ["text"] },
+ { "required": ["source"] }
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": ["default"]
+ }
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/jsonschema/jsonschema.go b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/jsonschema.go
new file mode 100644
index 00000000..b380e443
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/jsonschema/jsonschema.go
@@ -0,0 +1,40 @@
+package jsonschema
+
+import (
+ "embed"
+ "path/filepath"
+
+ "github.com/santhosh-tekuri/jsonschema/v6"
+)
+
+const (
+ V1Schema = "/golangci.v1.jsonschema.json"
+ NextSchema = "/golangci.next.jsonschema.json"
+)
+
+//go:embed golangci.next.jsonschema.json golangci.v1.jsonschema.json
+var content embed.FS
+
+type EmbedLoader struct {
+ jsonschema.FileLoader
+}
+
+func NewEmbedLoader() *EmbedLoader {
+ return &EmbedLoader{}
+}
+
+func (f *EmbedLoader) Load(uri string) (any, error) {
+ p, err := f.ToFile(uri)
+ if err != nil {
+ return nil, err
+ }
+
+ file, err := content.Open(filepath.Base(p))
+ if err != nil {
+ return nil, err
+ }
+
+ defer func() { _ = file.Close() }()
+
+ return jsonschema.UnmarshalJSON(file)
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/cache.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/cache.go
index 9772841c..094fe630 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/cache.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/cache.go
@@ -41,7 +41,7 @@ func newCacheCommand() *cacheCommand {
Short: "Show cache status",
Args: cobra.NoArgs,
ValidArgsFunction: cobra.NoFileCompletions,
- Run: c.executeStatus,
+ RunE: c.executeStatus,
},
)
@@ -51,7 +51,10 @@ func newCacheCommand() *cacheCommand {
}
func (*cacheCommand) executeClean(_ *cobra.Command, _ []string) error {
- cacheDir := cache.DefaultDir()
+ cacheDir, err := cache.DefaultDir()
+ if err != nil {
+ return err
+ }
if err := os.RemoveAll(cacheDir); err != nil {
return fmt.Errorf("failed to remove dir %s: %w", cacheDir, err)
@@ -60,8 +63,11 @@ func (*cacheCommand) executeClean(_ *cobra.Command, _ []string) error {
return nil
}
-func (*cacheCommand) executeStatus(_ *cobra.Command, _ []string) {
- cacheDir := cache.DefaultDir()
+func (*cacheCommand) executeStatus(_ *cobra.Command, _ []string) error {
+ cacheDir, err := cache.DefaultDir()
+ if err != nil {
+ return err
+ }
_, _ = fmt.Fprintf(logutils.StdOut, "Dir: %s\n", cacheDir)
@@ -69,6 +75,8 @@ func (*cacheCommand) executeStatus(_ *cobra.Command, _ []string) {
if err == nil {
_, _ = fmt.Fprintf(logutils.StdOut, "Size: %s\n", fsutils.PrettifyBytesCount(cacheSizeBytes))
}
+
+ return nil
}
func dirSizeBytes(path string) (int64, error) {
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go
index b1889fa4..79945eb0 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config.go
@@ -24,9 +24,8 @@ type configCommand struct {
viper *viper.Viper
cmd *cobra.Command
- opts config.LoaderOptions
- verifyOpts verifyOptions
- pathOpts pathOptions
+ opts config.LoaderOptions
+ pathOpts pathOptions
buildInfo BuildInfo
@@ -78,11 +77,6 @@ func newConfigCommand(log logutils.Log, info BuildInfo) *configCommand {
setupConfigFileFlagSet(flagSet, &c.opts)
- // ex: --schema jsonschema/golangci.next.jsonschema.json
- verifyFlagSet := verifyCommand.Flags()
- verifyFlagSet.StringVar(&c.verifyOpts.schemaURL, "schema", "", color.GreenString("JSON schema URL"))
- _ = verifyFlagSet.MarkHidden("schema")
-
pathFlagSet := pathCommand.Flags()
pathFlagSet.BoolVar(&c.pathOpts.JSON, "json", false, color.GreenString("Display as JSON"))
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go
index 7281e088..8e99c7ee 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/config_verify.go
@@ -1,31 +1,23 @@
package commands
import (
- "context"
"encoding/json"
"errors"
"fmt"
- "net/http"
"os"
"path/filepath"
"strconv"
"strings"
- "time"
- hcversion "github.com/hashicorp/go-version"
"github.com/pelletier/go-toml/v2"
"github.com/santhosh-tekuri/jsonschema/v6"
"github.com/spf13/cobra"
- "github.com/spf13/pflag"
"go.yaml.in/yaml/v3"
+ jsonsch "github.com/golangci/golangci-lint/v2/jsonschema"
"github.com/golangci/golangci-lint/v2/pkg/exitcodes"
)
-type verifyOptions struct {
- schemaURL string // For debugging purpose only (Flag only).
-}
-
func (c *configCommand) executeVerify(cmd *cobra.Command, _ []string) error {
usedConfigFile := c.getUsedConfig()
if usedConfigFile == "" {
@@ -33,14 +25,9 @@ func (c *configCommand) executeVerify(cmd *cobra.Command, _ []string) error {
os.Exit(exitcodes.NoConfigFileDetected)
}
- schemaURL, err := createSchemaURL(cmd.Flags(), c.buildInfo)
- if err != nil {
- return fmt.Errorf("get JSON schema: %w", err)
- }
+ c.log.Infof("Verifying the configuration file %q with the JSON Schema", usedConfigFile)
- c.log.Infof("Verifying the configuration file %q with the JSON Schema from %s", usedConfigFile, schemaURL)
-
- err = validateConfiguration(schemaURL, usedConfigFile)
+ err := validateConfiguration(jsonsch.NextSchema, usedConfigFile)
if err != nil {
var v *jsonschema.ValidationError
if !errors.As(err, &v) {
@@ -55,85 +42,12 @@ func (c *configCommand) executeVerify(cmd *cobra.Command, _ []string) error {
return nil
}
-func createSchemaURL(flags *pflag.FlagSet, buildInfo BuildInfo) (string, error) {
- schemaURL, err := flags.GetString("schema")
- if err != nil {
- return "", fmt.Errorf("get schema flag: %w", err)
- }
-
- if schemaURL != "" {
- return schemaURL, nil
- }
-
- switch {
- case buildInfo.Version != "" && buildInfo.Version != "(devel)":
- version, err := hcversion.NewVersion(buildInfo.Version)
- if err != nil {
- return "", fmt.Errorf("parse version: %w", err)
- }
-
- if version.Core().Equal(hcversion.Must(hcversion.NewVersion("v0.0.0"))) {
- commit, err := extractCommitHash(buildInfo)
- if err != nil {
- return "", err
- }
-
- return fmt.Sprintf("https://raw.githubusercontent.com/golangci/golangci-lint/%s/jsonschema/golangci.next.jsonschema.json",
- commit), nil
- }
-
- return fmt.Sprintf("https://golangci-lint.run/jsonschema/golangci.v%d.%d.jsonschema.json",
- version.Segments()[0], version.Segments()[1]), nil
-
- case buildInfo.Commit != "" && buildInfo.Commit != "?":
- commit, err := extractCommitHash(buildInfo)
- if err != nil {
- return "", err
- }
-
- return fmt.Sprintf("https://raw.githubusercontent.com/golangci/golangci-lint/%s/jsonschema/golangci.next.jsonschema.json",
- commit), nil
-
- default:
- return "", errors.New("version not found")
- }
-}
-
-func extractCommitHash(buildInfo BuildInfo) (string, error) {
- if buildInfo.Commit == "" || buildInfo.Commit == "?" {
- return "", errors.New("empty commit information")
- }
-
- if buildInfo.Commit == "unknown" {
- return "", errors.New("unknown commit information")
- }
-
- commit := buildInfo.Commit
-
- if after, ok := strings.CutPrefix(commit, "("); ok {
- c, _, ok := strings.Cut(after, ",")
- if !ok {
- return "", errors.New("commit information not found")
- }
-
- commit = c
- }
-
- if commit == "unknown" {
- return "", errors.New("unknown commit information")
- }
-
- return commit, nil
-}
-
func validateConfiguration(schemaPath, targetFile string) error {
compiler := jsonschema.NewCompiler()
- compiler.UseLoader(jsonschema.SchemeURLLoader{
- "file": jsonschema.FileLoader{},
- "https": newJSONSchemaHTTPLoader(),
- })
+ compiler.UseLoader(jsonsch.NewEmbedLoader())
compiler.DefaultDraft(jsonschema.Draft7)
+ // The name is not us
schema, err := compiler.Compile(schemaPath)
if err != nil {
return fmt.Errorf("compile schema: %w", err)
@@ -209,33 +123,3 @@ func decodeTomlFile(filename string) (any, error) {
return m, nil
}
-
-type jsonschemaHTTPLoader struct {
- *http.Client
-}
-
-func newJSONSchemaHTTPLoader() *jsonschemaHTTPLoader {
- return &jsonschemaHTTPLoader{Client: &http.Client{
- Timeout: 2 * time.Second,
- }}
-}
-
-func (l jsonschemaHTTPLoader) Load(url string) (any, error) {
- req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, http.NoBody)
- if err != nil {
- return nil, err
- }
-
- resp, err := l.Do(req)
- if err != nil {
- return nil, err
- }
-
- defer resp.Body.Close()
-
- if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("%s returned status code %d", url, resp.StatusCode)
- }
-
- return jsonschema.UnmarshalJSON(resp.Body)
-}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go
index 63f6f2f1..df2a134a 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/builder.go
@@ -96,6 +96,7 @@ func (b Builder) clone(ctx context.Context) error {
"https://github.com/golangci/golangci-lint.git",
)
cmd.Dir = b.root
+ cmd.Env = filterGitEnviron(os.Environ())
output, err := cmd.CombinedOutput()
if err != nil {
@@ -280,3 +281,33 @@ func sanitizeVersion(v string) string {
return strings.Join(strings.FieldsFunc(v, fn), "")
}
+
+// Inspired by https://github.com/pre-commit/pre-commit/blob/f5678bf4ac35cffc0ff7174ad85f7fdc2a5c977e/pre_commit/git.py#L27
+func filterGitEnviron(envs []string) []string {
+ var filtered []string
+
+ for _, env := range envs {
+ if !strings.HasPrefix(env, "GIT_") {
+ filtered = append(filtered, env)
+ continue
+ }
+
+ if strings.HasPrefix(env, "GIT_CONFIG_KEY_") || strings.HasPrefix(env, "GIT_CONFIG_VALUE_") {
+ filtered = append(filtered, env)
+ continue
+ }
+
+ key, _, _ := strings.Cut(env, "=")
+
+ switch key {
+ case "GIT_EXEC_PATH", "GIT_SSH", "GIT_SSH_COMMAND", "GIT_SSL_CAINFO",
+ "GIT_SSL_NO_VERIFY", "GIT_CONFIG_COUNT",
+ "GIT_HTTP_PROXY_AUTHMETHOD",
+ "GIT_ALLOW_PROTOCOL",
+ "GIT_ASKPASS":
+ filtered = append(filtered, env)
+ }
+ }
+
+ return filtered
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate.go
index 69b6c7c4..d44804f5 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate.go
@@ -1,14 +1,13 @@
package migrate
import (
- "github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/ptr"
"github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone"
"github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versiontwo"
)
func ToConfig(old *versionone.Config) *versiontwo.Config {
return &versiontwo.Config{
- Version: ptr.Pointer("2"),
+ Version: new("2"),
Linters: toLinters(old),
Formatters: toFormatters(old),
Issues: toIssues(old),
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters.go
index c070119b..9284da37 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters.go
@@ -22,9 +22,9 @@ func toLinters(old *versionone.Config) versiontwo.Linters {
func getDefaultName(old versionone.Linters) *string {
switch {
case ptr.Deref(old.DisableAll):
- return ptr.Pointer("none")
+ return new("none")
case ptr.Deref(old.EnableAll):
- return ptr.Pointer("all")
+ return new("all")
default:
return nil // standard is the default
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_exclusions.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_exclusions.go
index aac4d381..18c3176a 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_exclusions.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_exclusions.go
@@ -21,7 +21,7 @@ func toExclusions(old *versionone.Config) versiontwo.LinterExclusions {
func toExclusionGenerated(excludeGenerated *string) *string {
if excludeGenerated == nil || ptr.Deref(excludeGenerated) == "" {
- return ptr.Pointer("lax")
+ return new("lax")
}
if ptr.Deref(excludeGenerated) == "strict" {
@@ -83,8 +83,8 @@ func toExclusionRules(old *versionone.Config) []versiontwo.ExcludeRule {
for _, pattern := range old.Issues.ExcludePatterns {
results = append(results, versiontwo.ExcludeRule{
BaseRule: versiontwo.BaseRule{
- Path: ptr.Pointer(`(.+)\.go$`),
- Text: addPrefix(old.Issues, ptr.Pointer(pattern)),
+ Path: new(`(.+)\.go$`),
+ Text: addPrefix(old.Issues, new(pattern)),
},
})
}
@@ -102,7 +102,7 @@ func addPrefix(old versionone.Issues, s *string) *string {
prefix = "(?i)"
}
- return ptr.Pointer(prefix + ptr.Deref(s))
+ return new(prefix + ptr.Deref(s))
}
func linterTestExclusions(old versionone.LintersSettings) []versiontwo.ExcludeRule {
@@ -128,7 +128,7 @@ func linterTestExclusions(old versionone.LintersSettings) []versiontwo.ExcludeRu
return []versiontwo.ExcludeRule{{
BaseRule: versiontwo.BaseRule{
Linters: excludedTestLinters,
- Path: ptr.Pointer(`(.+)_test\.go`),
+ Path: new(`(.+)_test\.go`),
},
}}
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_settings.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_settings.go
index 4656842d..b831143d 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_settings.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_linters_settings.go
@@ -268,7 +268,7 @@ func toForbidigoSettings(old versionone.ForbidigoSettings) versiontwo.ForbidigoS
}
settings.Forbid = append(settings.Forbid, versiontwo.ForbidigoPattern{
- Pattern: ptr.Pointer(string(buffer)),
+ Pattern: new(string(buffer)),
})
continue
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_output.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_output.go
index e76f8e44..b41aa3bc 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_output.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/migrate_output.go
@@ -21,52 +21,52 @@ func toOutput(old *versionone.Config) versiontwo.Output {
formats.Text.PrintLinterName = old.Output.PrintLinterName
formats.Text.PrintIssuedLine = old.Output.PrintIssuedLine
formats.Text.Colors = nil // color is true by default (flags).
- formats.Text.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.Text.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "line-number":
formats.Text.PrintLinterName = old.Output.PrintLinterName
formats.Text.PrintIssuedLine = old.Output.PrintIssuedLine
- formats.Text.Colors = ptr.Pointer(false)
- formats.Text.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.Text.Colors = new(false)
+ formats.Text.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "json":
- formats.JSON.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.JSON.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "colored-tab":
formats.Tab.PrintLinterName = old.Output.PrintLinterName
formats.Tab.Colors = nil // Colors is true by default (flags).
- formats.Tab.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.Tab.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "tab":
formats.Tab.PrintLinterName = old.Output.PrintLinterName
- formats.Tab.Colors = ptr.Pointer(false)
- formats.Tab.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.Tab.Colors = new(false)
+ formats.Tab.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "html":
- formats.HTML.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.HTML.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "checkstyle":
- formats.Checkstyle.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.Checkstyle.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "code-climate":
- formats.CodeClimate.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.CodeClimate.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "junit-xml":
formats.JUnitXML.Extended = nil // Extended is false by default.
- formats.JUnitXML.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.JUnitXML.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "junit-xml-extended":
- formats.JUnitXML.Extended = ptr.Pointer(true)
- formats.JUnitXML.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.JUnitXML.Extended = new(true)
+ formats.JUnitXML.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "github-actions":
// Ignored
case "teamcity":
- formats.TeamCity.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.TeamCity.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
case "sarif":
- formats.Sarif.Path = ptr.Pointer(defaultFormatPath(ptr.Deref(format.Path)))
+ formats.Sarif.Path = new(defaultFormatPath(ptr.Deref(format.Path)))
}
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/ptr/ptr.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/ptr/ptr.go
index b0c7974e..eadb6d4f 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/ptr/ptr.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/ptr/ptr.go
@@ -8,5 +8,3 @@ func Deref[T any](v *T) T {
return *v
}
-
-func Pointer[T any](v T) *T { return &v }
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/linters_settings.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/linters_settings.go
index 3c641541..f057a4c3 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/linters_settings.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/linters_settings.go
@@ -246,7 +246,7 @@ type ForbidigoPattern struct {
func (p *ForbidigoPattern) UnmarshalText(text []byte) error {
// Validation happens when instantiating forbidigo.
- p.patternString = ptr.Pointer(string(text))
+ p.patternString = new(string(text))
return nil
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/output.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/output.go
index a3d86fc1..b3e29caf 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/output.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/versionone/output.go
@@ -2,8 +2,6 @@ package versionone
import (
"strings"
-
- "github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/ptr"
)
type Output struct {
@@ -28,8 +26,8 @@ func (p *OutputFormats) UnmarshalText(text []byte) error {
format, path, _ := strings.Cut(item, ":")
*p = append(*p, OutputFormat{
- Path: ptr.Pointer(path),
- Format: ptr.Pointer(format),
+ Path: new(path),
+ Format: new(format),
})
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go
index 7012e922..cfc5eb01 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/migrate.go
@@ -7,12 +7,13 @@ import (
"path/filepath"
"strings"
- "github.com/charmbracelet/lipgloss"
+ "charm.land/lipgloss/v2"
"github.com/fatih/color"
"github.com/santhosh-tekuri/jsonschema/v6"
"github.com/spf13/cobra"
"github.com/spf13/viper"
+ jsonsch "github.com/golangci/golangci-lint/v2/jsonschema"
"github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate"
"github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/fakeloader"
"github.com/golangci/golangci-lint/v2/pkg/commands/internal/migrate/parser"
@@ -153,7 +154,7 @@ func (c *migrateCommand) preRunE(cmd *cobra.Command, _ []string) error {
c.log.Infof("Validating v1 configuration file: %s", usedConfigFile)
- err := validateConfiguration("https://golangci-lint.run/jsonschema/golangci.v1.jsonschema.json", usedConfigFile)
+ err := validateConfiguration(jsonsch.V1Schema, usedConfigFile)
if err != nil {
var v *jsonschema.ValidationError
if !errors.As(err, &v) {
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go
index a9a3495a..a7efa264 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/commands/run.go
@@ -250,8 +250,7 @@ func (c *runCommand) execute(_ *cobra.Command, _ []string) {
if err := c.runAndPrint(ctx); err != nil {
c.log.Errorf("Running error: %s", err)
if c.exitCode == exitcodes.Success {
- var exitErr *exitcodes.ExitError
- if errors.As(err, &exitErr) {
+ if exitErr, ok := errors.AsType[*exitcodes.ExitError](err); ok {
c.exitCode = exitErr.Code
} else {
c.exitCode = exitcodes.Failure
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/base_loader.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/base_loader.go
index 9ad332ac..1ebfc9af 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/base_loader.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/base_loader.go
@@ -155,8 +155,7 @@ func (l *BaseLoader) getConfigSearchPaths() []string {
func (l *BaseLoader) parseConfig() error {
if err := l.viper.ReadInConfig(); err != nil {
- var configFileNotFoundError viper.ConfigFileNotFoundError
- if errors.As(err, &configFileNotFoundError) {
+ if _, ok := errors.AsType[viper.ConfigFileNotFoundError](err); ok {
// Load configuration from flags only.
err = l.viper.Unmarshal(l.cfg, customDecoderHook())
if err != nil {
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/formatters_settings.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/formatters_settings.go
index d99354ba..bb7ad18f 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/formatters_settings.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/formatters_settings.go
@@ -42,12 +42,21 @@ type GoFmtRewriteRule struct {
}
type GoFumptSettings struct {
- ModulePath string `mapstructure:"module-path"`
- ExtraRules bool `mapstructure:"extra-rules"`
+ ModulePath string `mapstructure:"module-path"`
+ Extra GoFumptExtra `mapstructure:"extra"`
+
+ // Deprecated: use Extra instead.
+ ExtraRules bool `mapstructure:"extra-rules"`
LangVersion string `mapstructure:"-"`
}
+type GoFumptExtra struct {
+ GroupParams bool `mapstructure:"group-params"`
+ ClotheReturns bool `mapstructure:"clothe-returns"`
+ BalanceCalls bool `mapstructure:"balance-calls"`
+}
+
type GoImportsSettings struct {
LocalPrefixes []string `mapstructure:"local-prefixes"`
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go
index 3f7193bd..e8561197 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go
@@ -41,6 +41,11 @@ var defaultLintersSettings = LintersSettings{
ExplicitExhaustiveMap: false,
ExplicitExhaustiveSwitch: false,
},
+ Fatcontext: FatcontextSettings{
+ CheckStructPointers: false,
+ CheckLoops: true,
+ CheckFunctionLiterals: true,
+ },
Forbidigo: ForbidigoSettings{
ExcludeGodocExamples: true,
},
@@ -63,6 +68,7 @@ var defaultLintersSettings = LintersSettings{
MinOccurrencesCount: 3,
NumberMin: 3,
NumberMax: 3,
+ ExcludeTypes: []string{"Call"},
IgnoreCalls: true,
},
Gocritic: GoCriticSettings{
@@ -141,17 +147,20 @@ var defaultLintersSettings = LintersSettings{
Predeclared: PredeclaredSettings{
Qualified: false,
},
- SlogLint: SlogLintSettings{
- NoMixedArgs: true,
- KVOnly: false,
- AttrOnly: false,
+ Sloglint: SloglintSettings{
NoGlobal: "",
Context: "",
StaticMsg: false,
+ MsgStyle: "",
+ NoMixedArgs: true,
+ KVOnly: false,
+ AttrOnly: false,
+ ArgsOnSepLines: false,
NoRawKeys: false,
+ AllowedKeys: []string{},
+ ForbiddenKeys: []string{},
KeyNamingCase: "",
- ForbiddenKeys: nil,
- ArgsOnSepLines: false,
+ CustomFuncs: []SloglintCustomFunc{},
},
TagAlign: TagAlignSettings{
Align: true,
@@ -226,13 +235,14 @@ var defaultLintersSettings = LintersSettings{
ForceExclusiveShortDeclarations: false,
},
WSLv5: WSLv5Settings{
- AllowFirstInBlock: true,
- AllowWholeBlock: false,
- BranchMaxLines: 2,
- CaseMaxLines: 0,
- Default: "default",
- Enable: nil,
- Disable: nil,
+ AllowFirstInBlock: true,
+ AllowWholeBlock: false,
+ BranchMaxLines: 2,
+ CaseMaxLines: 0,
+ CuddleMaxStatements: 1,
+ Default: "default",
+ Enable: nil,
+ Disable: nil,
},
}
@@ -241,6 +251,7 @@ type LintersSettings struct {
Asasalint AsasalintSettings `mapstructure:"asasalint"`
BiDiChk BiDiChkSettings `mapstructure:"bidichk"`
+ BodyClose BodyCloseSettings `mapstructure:"bodyclose"`
CopyLoopVar CopyLoopVarSettings `mapstructure:"copyloopvar"`
Cyclop CyclopSettings `mapstructure:"cyclop"`
Decorder DecorderSettings `mapstructure:"decorder"`
@@ -254,6 +265,7 @@ type LintersSettings struct {
ErrorLint ErrorLintSettings `mapstructure:"errorlint"`
Exhaustive ExhaustiveSettings `mapstructure:"exhaustive"`
Exhaustruct ExhaustructSettings `mapstructure:"exhaustruct"`
+ Exhaustructv5 ExhaustructV5Settings `mapstructure:"exhaustruct_v5"`
Fatcontext FatcontextSettings `mapstructure:"fatcontext"`
Forbidigo ForbidigoSettings `mapstructure:"forbidigo"`
FuncOrder FuncOrderSettings `mapstructure:"funcorder"`
@@ -270,6 +282,7 @@ type LintersSettings struct {
Goheader GoHeaderSettings `mapstructure:"goheader"`
GoModDirectives GoModDirectivesSettings `mapstructure:"gomoddirectives"`
Gomodguard GoModGuardSettings `mapstructure:"gomodguard"`
+ Gomodguardv2 GoModGuardv2Settings `mapstructure:"gomodguard_v2"`
Gosec GoSecSettings `mapstructure:"gosec"`
Gosmopolitan GosmopolitanSettings `mapstructure:"gosmopolitan"`
Unqueryvet UnqueryvetSettings `mapstructure:"unqueryvet"`
@@ -306,7 +319,7 @@ type LintersSettings struct {
Recvcheck RecvcheckSettings `mapstructure:"recvcheck"`
Revive ReviveSettings `mapstructure:"revive"`
RowsErrCheck RowsErrCheckSettings `mapstructure:"rowserrcheck"`
- SlogLint SlogLintSettings `mapstructure:"sloglint"`
+ Sloglint SloglintSettings `mapstructure:"sloglint"`
Spancheck SpancheckSettings `mapstructure:"spancheck"`
Staticcheck StaticCheckSettings `mapstructure:"staticcheck"`
TagAlign TagAlignSettings `mapstructure:"tagalign"`
@@ -359,6 +372,10 @@ type BiDiChkSettings struct {
PopDirectionalIsolate bool `mapstructure:"pop-directional-isolate"`
}
+type BodyCloseSettings struct {
+ CheckConsumption bool `mapstructure:"check-consumption"`
+}
+
type CopyLoopVarSettings struct {
CheckAlias bool `mapstructure:"check-alias"`
}
@@ -404,9 +421,10 @@ type DuplSettings struct {
}
type DupWordSettings struct {
- Keywords []string `mapstructure:"keywords"`
- Ignore []string `mapstructure:"ignore"`
- CommentsOnly bool `mapstructure:"comments-only"`
+ Keywords []string `mapstructure:"keywords"`
+ Ignore []string `mapstructure:"ignore"`
+ CommentsOnly bool `mapstructure:"comments-only"`
+ SkipRawStrings bool `mapstructure:"skip-raw-strings"`
}
type EmbeddedStructFieldCheckSettings struct {
@@ -452,6 +470,7 @@ type ExhaustiveSettings struct {
DefaultCaseRequired bool `mapstructure:"default-case-required"`
}
+// Deprecated: use ExhaustructV5Settings instead.
type ExhaustructSettings struct {
Include []string `mapstructure:"include"`
Exclude []string `mapstructure:"exclude"`
@@ -461,8 +480,21 @@ type ExhaustructSettings struct {
AllowEmptyDeclarations bool `mapstructure:"allow-empty-declarations"`
}
+type ExhaustructV5Settings struct {
+ EnforcePatterns []string `mapstructure:"enforce-patterns"`
+ IgnorePatterns []string `mapstructure:"ignore-patterns"`
+ OptionalPatterns []string `mapstructure:"optional-patterns"`
+ AllowEmpty bool `mapstructure:"allow-empty"`
+ AllowEmptyPatterns []string `mapstructure:"allow-empty-patterns"`
+ AllowEmptyReturns bool `mapstructure:"allow-empty-returns"`
+ AllowEmptyDeclarations bool `mapstructure:"allow-empty-declarations"`
+ ExplicitMode bool `mapstructure:"explicit-mode"`
+}
+
type FatcontextSettings struct {
- CheckStructPointers bool `mapstructure:"check-struct-pointers"`
+ CheckStructPointers bool `mapstructure:"check-struct-pointers"`
+ CheckLoops bool `mapstructure:"check-loops"`
+ CheckFunctionLiterals bool `mapstructure:"check-function-literals"`
}
type ForbidigoSettings struct {
@@ -481,6 +513,7 @@ type FuncOrderSettings struct {
Constructor bool `mapstructure:"constructor,omitempty"`
StructMethod bool `mapstructure:"struct-method,omitempty"`
Alphabetical bool `mapstructure:"alphabetical,omitempty"`
+ Function bool `mapstructure:"function,omitempty"`
}
type FunlenSettings struct {
@@ -523,9 +556,20 @@ type GoConstSettings struct {
ParseNumbers bool `mapstructure:"numbers"`
NumberMin int `mapstructure:"min"`
NumberMax int `mapstructure:"max"`
- IgnoreCalls bool `mapstructure:"ignore-calls"`
+ ExcludeTypes []string `mapstructure:"exclude-types"`
FindDuplicates bool `mapstructure:"find-duplicates"`
EvalConstExpressions bool `mapstructure:"eval-const-expressions"`
+ IgnoreFunctions []string `mapstructure:"ignore-functions"`
+ IgnoreMapKeys bool `mapstructure:"ignore-map-keys"`
+
+ // This option cannot be managed with `linters.exclusions.rules`.
+ // Because the linter counts occurrences across all files in the package.
+ IgnoreTests bool `mapstructure:"ignore-tests"`
+
+ // NOTE(ldez): `ignore-calls` was here to have the same options as goconst as CLI.
+ //
+ // Deprecated: use ExcludeTypes instead.
+ IgnoreCalls bool `mapstructure:"ignore-calls"`
// Deprecated: use IgnoreStringValues instead.
IgnoreStrings string `mapstructure:"ignore-strings"`
@@ -586,7 +630,9 @@ type GoHeaderSettings struct {
type GoModDirectivesSettings struct {
ReplaceAllowList []string `mapstructure:"replace-allow-list"`
ReplaceLocal bool `mapstructure:"replace-local"`
+ ReplaceAllowAll bool `mapstructure:"replace-allow-all"`
ExcludeForbidden bool `mapstructure:"exclude-forbidden"`
+ IgnoreForbidden bool `mapstructure:"ignore-forbidden"`
RetractAllowNoExplanation bool `mapstructure:"retract-allow-no-explanation"`
ToolchainForbidden bool `mapstructure:"toolchain-forbidden"`
ToolchainPattern string `mapstructure:"toolchain-pattern"`
@@ -596,6 +642,26 @@ type GoModDirectivesSettings struct {
CheckModulePath bool `mapstructure:"check-module-path"`
}
+type GoModGuardv2Settings struct {
+ Allowed []GoModGuardv2Base `mapstructure:"allowed"`
+ Blocked []GoModGuardv2Blocked `mapstructure:"blocked"`
+ LocalReplaceDirectives bool `mapstructure:"local-replace-directives"`
+}
+
+type GoModGuardv2Base struct {
+ Module string `mapstructure:"module"`
+ Version string `mapstructure:"version"`
+ MatchType string `mapstructure:"match-type"`
+}
+
+type GoModGuardv2Blocked struct {
+ GoModGuardv2Base `mapstructure:",squash"`
+
+ Recommendations []string `mapstructure:"recommendations"`
+ Reason string `mapstructure:"reason"`
+}
+
+// Deprecated: use GoModGuardv2Settings instead.
type GoModGuardSettings struct {
Allowed GoModGuardAllowed `mapstructure:"allowed"`
Blocked GoModGuardBlocked `mapstructure:"blocked"`
@@ -792,13 +858,15 @@ type NoLintLintSettings struct {
}
type NoNamedReturnsSettings struct {
- ReportErrorInDefer bool `mapstructure:"report-error-in-defer"`
+ ReportErrorInDefer bool `mapstructure:"report-error-in-defer"`
+ AllowUnusedNamedReturns bool `mapstructure:"allow-unused-named-returns"`
}
type ParallelTestSettings struct {
Go string `mapstructure:"-"`
IgnoreMissing bool `mapstructure:"ignore-missing"`
IgnoreMissingSubtests bool `mapstructure:"ignore-missing-subtests"`
+ CheckCleanup bool `mapstructure:"check-cleanup"`
}
type PerfSprintSettings struct {
@@ -882,18 +950,26 @@ type RowsErrCheckSettings struct {
Packages []string `mapstructure:"packages"`
}
-type SlogLintSettings struct {
- NoMixedArgs bool `mapstructure:"no-mixed-args"`
- KVOnly bool `mapstructure:"kv-only"`
- AttrOnly bool `mapstructure:"attr-only"`
- NoGlobal string `mapstructure:"no-global"`
- Context string `mapstructure:"context"`
- StaticMsg bool `mapstructure:"static-msg"`
- MsgStyle string `mapstructure:"msg-style"`
- NoRawKeys bool `mapstructure:"no-raw-keys"`
- KeyNamingCase string `mapstructure:"key-naming-case"`
- ForbiddenKeys []string `mapstructure:"forbidden-keys"`
- ArgsOnSepLines bool `mapstructure:"args-on-sep-lines"`
+type SloglintSettings struct {
+ NoGlobal string `mapstructure:"no-global"`
+ Context string `mapstructure:"context"`
+ StaticMsg bool `mapstructure:"static-msg"`
+ MsgStyle string `mapstructure:"msg-style"`
+ NoMixedArgs bool `mapstructure:"no-mixed-args"`
+ KVOnly bool `mapstructure:"kv-only"`
+ AttrOnly bool `mapstructure:"attr-only"`
+ ArgsOnSepLines bool `mapstructure:"args-on-sep-lines"`
+ NoRawKeys bool `mapstructure:"no-raw-keys"`
+ AllowedKeys []string `mapstructure:"allowed-keys"`
+ ForbiddenKeys []string `mapstructure:"forbidden-keys"`
+ KeyNamingCase string `mapstructure:"key-naming-case"`
+ CustomFuncs []SloglintCustomFunc `mapstructure:"custom-funcs"`
+}
+
+type SloglintCustomFunc struct {
+ Name string `mapstructure:"name"`
+ MsgPos int `mapstructure:"msg-pos"`
+ ArgsPos int `mapstructure:"args-pos"`
}
type SpancheckSettings struct {
@@ -1131,13 +1207,14 @@ type WSLv4Settings struct {
}
type WSLv5Settings struct {
- AllowFirstInBlock bool `mapstructure:"allow-first-in-block"`
- AllowWholeBlock bool `mapstructure:"allow-whole-block"`
- BranchMaxLines int `mapstructure:"branch-max-lines"`
- CaseMaxLines int `mapstructure:"case-max-lines"`
- Default string `mapstructure:"default"`
- Enable []string `mapstructure:"enable"`
- Disable []string `mapstructure:"disable"`
+ AllowFirstInBlock bool `mapstructure:"allow-first-in-block"`
+ AllowWholeBlock bool `mapstructure:"allow-whole-block"`
+ BranchMaxLines int `mapstructure:"branch-max-lines"`
+ CaseMaxLines int `mapstructure:"case-max-lines"`
+ CuddleMaxStatements int `mapstructure:"cuddle-max-statements"`
+ Default string `mapstructure:"default"`
+ Enable []string `mapstructure:"enable"`
+ Disable []string `mapstructure:"disable"`
}
// CustomLinterSettings encapsulates the meta-data of a private linter.
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_action_cache.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_action_cache.go
index 1fafbca5..8fcacf6e 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_action_cache.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_action_cache.go
@@ -30,35 +30,74 @@ func (act *action) loadCachedFacts() bool {
return true // no need to load facts
}
- return act.loadPersistedFacts()
+ if !act.loadPersistedFacts() {
+ return false
+ }
+
+ // The cache only stores the facts a package produces about its own objects.
+ // The facts a package re-exports from its dependencies (see exportedFrom) are not persisted,
+ // to avoid duplicating them in every cache entry (which grows quadratically with the import graph).
+ // Instead, we rebuild them in memory here by inheriting from the dependencies,
+ // exactly like analyze() does for packages analyzed from source.
+ // This is safe because every dependency is fully analyzed (from cache or source) before this package is loaded,
+ // so their facts are already available.
+ act.inheritFactsFromDeps()
+
+ return true
}()
+
act.loadCachedFactsDone = true
act.loadCachedFactsOk = res
+
return res
}
+// inheritFactsFromDeps rebuilds, in memory,
+// the facts re-exported from this action's dependencies (vertical edges: same analyzer, different package),
+// mirroring the inheritance performed by analyze() for packages analyzed from source.
+func (act *action) inheritFactsFromDeps() {
+ for _, dep := range act.Deps {
+ if dep.Package == act.Package || dep.Analyzer != act.Analyzer {
+ continue
+ }
+
+ inheritFacts(act, dep)
+ }
+}
+
func (act *action) persistFactsToCache() error {
analyzer := act.Analyzer
+
if len(analyzer.FactTypes) == 0 {
return nil
}
- // Merge new facts into the package and persist them.
+ // Persist only the facts this package produces about its own objects.
+ //
+ // Facts about objects from other packages (inherited through this package's export data) are intentionally NOT persisted:
+ // doing so duplicates them in every cache entry along the import graph and makes the cache grow quadratically.
+ // When a package is restored from the cache,
+ // those re-exported facts are rebuilt in memory by inheriting from its dependencies (see inheritFactsFromDeps).
+
var facts []Fact
+
for key, fact := range act.packageFacts {
if key.pkg != act.Package.Types {
- // The fact is from inherited facts from another package
+ // The fact is inherited from another package.
continue
}
+
facts = append(facts, Fact{
Path: "",
Fact: fact,
})
}
+
for key, fact := range act.objectFacts {
obj := key.obj
+
if obj.Pkg() != act.Package.Types {
- // The fact is from inherited facts from another package
+ // The fact is inherited from another package.
continue
}
@@ -89,6 +128,7 @@ func (act *action) loadPersistedFacts() bool {
}
factsCacheDebugf("No cached facts for package %q and analyzer %s", act.Package.Name, act.Analyzer.Name)
+
return false
}
@@ -100,6 +140,7 @@ func (act *action) loadPersistedFacts() bool {
act.packageFacts[key] = f.Fact
continue
}
+
obj, err := objectpath.Object(act.Package.Types, objectpath.Path(f.Path))
if err != nil {
// Be lenient about these errors.
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_loadingpackage.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_loadingpackage.go
index e01d3eaa..f918be63 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_loadingpackage.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goanalysis/runner_loadingpackage.go
@@ -531,8 +531,8 @@ func sizeOfReflectValueTreeBytes(rv reflect.Value, visitedPtrs map[uintptr]struc
return sizeOfReflectValueTreeBytes(rv.Elem(), visitedPtrs)
case reflect.Struct:
ret := 0
- for i := range rv.NumField() {
- ret += sizeOfReflectValueTreeBytes(rv.Field(i), visitedPtrs)
+ for _, field := range rv.Fields() {
+ ret += sizeOfReflectValueTreeBytes(field, visitedPtrs)
}
return ret
case reflect.Slice, reflect.Array, reflect.Chan:
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/section/standard_list.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/section/standard_list.go
index a7787409..120acb13 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/section/standard_list.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gci/internal/section/standard_list.go
@@ -1,6 +1,6 @@
package section
-// Code generated based on go1.26.0 X:boringcrypto,arenas,jsonv2,runtimesecret. DO NOT EDIT.
+// Code generated based on go1.27.0 Thu May 28 17:10:42 2026 -0700 X:boringcrypto,arenas,runtimesecret. DO NOT EDIT.
var standardPackages = map[string]struct{}{
"archive/tar": {},
@@ -33,6 +33,7 @@ var standardPackages = map[string]struct{}{
"crypto/hmac": {},
"crypto/hpke": {},
"crypto/md5": {},
+ "crypto/mldsa": {},
"crypto/mlkem": {},
"crypto/mlkem/mlkemtest": {},
"crypto/pbkdf2": {},
@@ -185,5 +186,6 @@ var standardPackages = map[string]struct{}{
"unicode/utf8": {},
"unique": {},
"unsafe": {},
+ "uuid": {},
"weak": {},
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gofmt/gofmt.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gofmt/gofmt.go
index 4d5ff863..38660a59 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gofmt/gofmt.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gofmt/gofmt.go
@@ -1,7 +1,7 @@
package gofmt
import (
- "github.com/golangci/gofmt/gofmt"
+ "github.com/golangci/gofmt"
"github.com/golangci/golangci-lint/v2/pkg/config"
)
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt/gofumpt.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt/gofumpt.go
index d8f5f2f7..1e3f7100 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt/gofumpt.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt/gofumpt.go
@@ -6,6 +6,7 @@ import (
gofumpt "mvdan.cc/gofumpt/format"
"github.com/golangci/golangci-lint/v2/pkg/config"
+ "github.com/golangci/golangci-lint/v2/pkg/goformatters/internal"
)
const Name = "gofumpt"
@@ -18,10 +19,19 @@ func New(settings *config.GoFumptSettings, goVersion string) *Formatter {
var options gofumpt.Options
if settings != nil {
+ if settings.ExtraRules {
+ internal.FormatterLogger.Warnf("gofumpt: `extra-rules` is deprecated, please use `extra.group-params` instead.")
+ }
+
options = gofumpt.Options{
LangVersion: getLangVersion(goVersion),
ModulePath: settings.ModulePath,
ExtraRules: settings.ExtraRules,
+ Extra: gofumpt.Extra{
+ GroupParams: settings.Extra.GroupParams,
+ ClotheReturns: settings.Extra.ClotheReturns,
+ BalanceCalls: settings.Extra.BalanceCalls,
+ },
}
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go
index f68c4d0a..95cf790b 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose/bodyclose.go
@@ -3,11 +3,21 @@ package bodyclose
import (
"github.com/timakin/bodyclose/passes/bodyclose"
+ "github.com/golangci/golangci-lint/v2/pkg/config"
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
)
-func New() *goanalysis.Linter {
+func New(settings *config.BodyCloseSettings) *goanalysis.Linter {
+ var cfg map[string]any
+
+ if settings != nil {
+ cfg = map[string]any{
+ "check-consumption": settings.CheckConsumption,
+ }
+ }
+
return goanalysis.
NewLinterFromAnalyzer(bodyclose.Analyzer).
+ WithConfig(cfg).
WithLoadMode(goanalysis.LoadModeTypesInfo)
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/clickhouselint/clickhouselint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/clickhouselint/clickhouselint.go
new file mode 100644
index 00000000..0459864b
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/clickhouselint/clickhouselint.go
@@ -0,0 +1,18 @@
+package clickhouselint
+
+import (
+ "github.com/ClickHouse/clickhouse-go-linter/passes/chbatchclose"
+ "github.com/ClickHouse/clickhouse-go-linter/passes/chrowserr"
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/golangci/golangci-lint/v2/pkg/goanalysis"
+)
+
+func New() *goanalysis.Linter {
+ return goanalysis.NewLinter(
+ "clickhouselint",
+ "Detects common mistakes with the ClickHouse native Go driver API.",
+ []*analysis.Analyzer{chrowserr.NewAnalyzer(), chbatchclose.NewAnalyzer()},
+ nil,
+ ).WithLoadMode(goanalysis.LoadModeTypesInfo)
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupword/dupword.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupword/dupword.go
index 0308534e..08ae1868 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupword/dupword.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/dupword/dupword.go
@@ -14,9 +14,10 @@ func New(settings *config.DupWordSettings) *goanalysis.Linter {
if settings != nil {
cfg = map[string]any{
- "keyword": strings.Join(settings.Keywords, ","),
- "ignore": strings.Join(settings.Ignore, ","),
- "comments-only": settings.CommentsOnly,
+ "keyword": strings.Join(settings.Keywords, ","),
+ "ignore": strings.Join(settings.Ignore, ","),
+ "comments-only": settings.CommentsOnly,
+ "skip-raw-strings": settings.SkipRawStrings,
}
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustruct/exhaustruct_v5.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustruct/exhaustruct_v5.go
new file mode 100644
index 00000000..eabfe1ae
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/exhaustruct/exhaustruct_v5.go
@@ -0,0 +1,34 @@
+package exhaustruct
+
+import (
+ exhaustruct "dev.gaijin.team/go/exhaustruct/v5/analyzer"
+
+ "github.com/golangci/golangci-lint/v2/pkg/config"
+ "github.com/golangci/golangci-lint/v2/pkg/goanalysis"
+ "github.com/golangci/golangci-lint/v2/pkg/golinters/internal"
+)
+
+func NewV5(settings *config.ExhaustructV5Settings) *goanalysis.Linter {
+ cfg := exhaustruct.Config{}
+
+ if settings != nil {
+ cfg.EnforcePatterns = settings.EnforcePatterns
+ cfg.IgnorePatterns = settings.IgnorePatterns
+ cfg.OptionalPatterns = settings.OptionalPatterns
+ cfg.AllowEmpty = settings.AllowEmpty
+ cfg.AllowEmptyPatterns = settings.AllowEmptyPatterns
+ cfg.AllowEmptyReturns = settings.AllowEmptyReturns
+ cfg.AllowEmptyDeclarations = settings.AllowEmptyDeclarations
+ cfg.ExplicitMode = settings.ExplicitMode
+ }
+
+ analyzer, err := exhaustruct.NewAnalyzerWithConfig(cfg)
+ if err != nil {
+ internal.LinterLogger.Fatalf("exhaustruct configuration: %v", err)
+ }
+
+ return goanalysis.
+ NewLinterFromAnalyzer(analyzer).
+ WithVersion(5). //nolint:mnd // It's the linter version.
+ WithLoadMode(goanalysis.LoadModeTypesInfo)
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/fatcontext/fatcontext.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/fatcontext/fatcontext.go
index 58933c66..656fd423 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/fatcontext/fatcontext.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/fatcontext/fatcontext.go
@@ -12,7 +12,9 @@ func New(settings *config.FatcontextSettings) *goanalysis.Linter {
if settings != nil {
cfg = map[string]any{
- analyzer.FlagCheckStructPointers: settings.CheckStructPointers,
+ analyzer.FlagCheckStructPointers: settings.CheckStructPointers,
+ analyzer.FlagCheckLoops: settings.CheckLoops,
+ analyzer.FlagCheckFunctionLiterals: settings.CheckFunctionLiterals,
}
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funcorder/funcorder.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funcorder/funcorder.go
index 06400753..aa918896 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funcorder/funcorder.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/funcorder/funcorder.go
@@ -15,6 +15,7 @@ func New(settings *config.FuncOrderSettings) *goanalysis.Linter {
analyzer.ConstructorCheckName: settings.Constructor,
analyzer.StructMethodCheckName: settings.StructMethod,
analyzer.AlphabeticalCheckName: settings.Alphabetical,
+ analyzer.FunctionCheckName: settings.Function,
}
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go
index b58d860c..4320c44c 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/goconst/goconst.go
@@ -2,6 +2,7 @@ package goconst
import (
"fmt"
+ "strings"
"sync"
goconstAPI "github.com/jgautheron/goconst"
@@ -48,8 +49,9 @@ func New(settings *config.GoConstSettings) *goanalysis.Linter {
}
func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]*goanalysis.Issue, error) {
- cfg := goconstAPI.Config{
+ cfg := &goconstAPI.Config{
IgnoreStrings: settings.IgnoreStringValues,
+ IgnoreTests: settings.IgnoreTests,
MatchWithConstants: settings.MatchWithConstants,
MinStringLength: settings.MinStringLen,
MinOccurrences: settings.MinOccurrencesCount,
@@ -59,16 +61,28 @@ func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]*goana
ExcludeTypes: map[goconstAPI.Type]bool{},
FindDuplicates: settings.FindDuplicates,
EvalConstExpressions: settings.EvalConstExpressions,
+ IgnoreFunctions: settings.IgnoreFunctions,
+ IgnoreMapKeys: settings.IgnoreMapKeys,
+ }
- // Should be managed with `linters.exclusions.rules`.
- IgnoreTests: false,
+ // There is no deprecation log for `IgnoreCalls` because the default is true.
+ // As the default of `ExcludeTypes` contains `call`,
+ // setting `IgnoreCalls` to false is the only way for a user to explicitly use the value `call`.
+ // TODO(ldez): `IgnoreCalls` must be removed if the next major version.
+ if !settings.IgnoreCalls && len(settings.ExcludeTypes) == 1 && strings.EqualFold(settings.ExcludeTypes[0], "call") {
+ settings.ExcludeTypes = nil
}
- if settings.IgnoreCalls {
- cfg.ExcludeTypes[goconstAPI.Call] = true
+ for _, k := range settings.ExcludeTypes {
+ typ, err := toType(k)
+ if err != nil {
+ return nil, err
+ }
+
+ cfg.ExcludeTypes[typ] = true
}
- lintIssues, err := goconstAPI.Run(pass.Files, pass.Fset, pass.TypesInfo, &cfg)
+ lintIssues, err := goconstAPI.Run(pass.Files, pass.Fset, pass.TypesInfo, cfg)
if err != nil {
return nil, err
}
@@ -111,3 +125,28 @@ func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]*goana
return res, nil
}
+
+func toType(v string) (goconstAPI.Type, error) {
+ switch strings.ToLower(v) {
+ case "assignment":
+ return goconstAPI.Assignment, nil
+
+ case "binary":
+ return goconstAPI.Binary, nil
+
+ case "case":
+ return goconstAPI.Case, nil
+
+ case "return":
+ return goconstAPI.Return, nil
+
+ case "call":
+ return goconstAPI.Call, nil
+
+ case "compositelit":
+ return goconstAPI.CompositeLit, nil
+
+ default:
+ return 0, fmt.Errorf("unknown type %s", v)
+ }
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go
index 0d017125..26c98adb 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go
@@ -46,18 +46,18 @@ func New(settings *config.GodoclintSettings) *goanalysis.Linter {
Disable: settings.Disable,
Options: &glconfig.PlainRuleOptions{
MaxLenLength: settings.Options.MaxLen.Length,
- MaxLenIncludeTests: pointer(true),
+ MaxLenIncludeTests: new(true),
MaxLenIgnorePatterns: []string{`^\+kubebuilder:`},
- PkgDocIncludeTests: pointer(false),
- SinglePkgDocIncludeTests: pointer(true),
- RequirePkgDocIncludeTests: pointer(false),
- RequireDocIncludeTests: pointer(true),
+ PkgDocIncludeTests: new(false),
+ SinglePkgDocIncludeTests: new(true),
+ RequirePkgDocIncludeTests: new(false),
+ RequireDocIncludeTests: new(true),
RequireDocIgnoreExported: settings.Options.RequireDoc.IgnoreExported,
RequireDocIgnoreUnexported: settings.Options.RequireDoc.IgnoreUnexported,
- StartWithNameIncludeTests: pointer(false),
+ StartWithNameIncludeTests: new(false),
StartWithNameIncludeUnexported: settings.Options.StartWithName.IncludeUnexported,
- RequireStdlibDoclinkIncludeTests: pointer(true),
- NoUnusedLinkIncludeTests: pointer(true),
+ RequireStdlibDoclinkIncludeTests: new(true),
+ NoUnusedLinkIncludeTests: new(true),
},
}
@@ -107,8 +107,6 @@ func checkSettings(settings *config.GodoclintSettings) error {
return nil
}
-func pointer[T any](v T) *T { return &v }
-
func deref[T any](v *T) T {
if v == nil {
var zero T
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofumpt/gofumpt.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofumpt/gofumpt.go
index 1ee7c833..69f61799 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofumpt/gofumpt.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gofumpt/gofumpt.go
@@ -13,7 +13,7 @@ func New(settings *config.GoFumptSettings) *goanalysis.Linter {
NewLinterFromAnalyzer(
goformatters.NewAnalyzer(
internal.LinterLogger.Child(gofumptbase.Name),
- "Check if code and import statements are formatted, with additional rules.",
+ "Enforce a stricter format than gofmt, while being backwards compatible.",
gofumptbase.New(settings, settings.LangVersion),
),
).
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go
index 817b5498..71c42c4e 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go
@@ -24,8 +24,10 @@ func New(settings *config.GoModDirectivesSettings) *goanalysis.Linter {
if settings != nil {
opts.ReplaceAllowLocal = settings.ReplaceLocal
opts.ReplaceAllowList = settings.ReplaceAllowList
+ opts.ReplaceAllowAll = settings.ReplaceAllowAll
opts.RetractAllowNoExplanation = settings.RetractAllowNoExplanation
opts.ExcludeForbidden = settings.ExcludeForbidden
+ opts.IgnoreForbidden = settings.IgnoreForbidden
opts.ToolchainForbidden = settings.ToolchainForbidden
opts.ToolForbidden = settings.ToolForbidden
opts.GoDebugForbidden = settings.GoDebugForbidden
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go
index 7d16f57b..b8bdd096 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard.go
@@ -87,3 +87,66 @@ func New(settings *config.GoModGuardSettings) *goanalysis.Linter {
}).
WithLoadMode(goanalysis.LoadModeSyntax)
}
+
+// Only used the set YAML struct tags.
+type v2YAML struct {
+ Allowed []goModGuardv2Base `yaml:"allowed,omitempty"`
+ Blocked []goModGuardv2Blocked `yaml:"blocked,omitempty"`
+ LocalReplaceDirectives bool `yaml:"local-replace-directives,omitempty"`
+}
+
+// Only used the set YAML struct tags.
+type goModGuardv2Base struct {
+ Module string `yaml:"module,omitempty"`
+ Version string `yaml:"version,omitempty"`
+ MatchType string `yaml:"match-type,omitempty"`
+}
+
+// Only used the set YAML struct tags.
+type goModGuardv2Blocked struct {
+ goModGuardv2Base `yaml:",inline"`
+
+ Recommendations []string `yaml:"recommendations,omitempty"`
+ Reason string `yaml:"reason,omitempty"`
+}
+
+func Migration(old *config.GoModGuardSettings) any {
+ if old == nil {
+ return nil
+ }
+
+ if len(old.Allowed.Modules) == 0 && len(old.Allowed.Domains) == 0 && len(old.Blocked.Modules) == 0 && !old.Blocked.LocalReplaceDirectives {
+ return nil
+ }
+
+ cfg := &v2YAML{
+ LocalReplaceDirectives: old.Blocked.LocalReplaceDirectives,
+ }
+
+ for _, module := range old.Allowed.Modules {
+ cfg.Allowed = append(cfg.Allowed, goModGuardv2Base{
+ Module: module,
+ })
+ }
+
+ for _, domain := range old.Allowed.Domains {
+ cfg.Allowed = append(cfg.Allowed, goModGuardv2Base{
+ Module: domain + "/.*",
+ MatchType: "regex",
+ })
+ }
+
+ for _, blocked := range old.Blocked.Modules {
+ for name, module := range blocked {
+ cfg.Blocked = append(cfg.Blocked, goModGuardv2Blocked{
+ goModGuardv2Base: goModGuardv2Base{
+ Module: name,
+ },
+ Recommendations: module.Recommendations,
+ Reason: module.Reason,
+ })
+ }
+ }
+
+ return cfg
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard_v2.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard_v2.go
new file mode 100644
index 00000000..d25e7206
--- /dev/null
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard/gomodguard_v2.go
@@ -0,0 +1,106 @@
+package gomodguard
+
+import (
+ "sync"
+
+ "github.com/Masterminds/semver/v3"
+ "github.com/ryancurrah/gomodguard/v2"
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/golangci/golangci-lint/v2/pkg/config"
+ "github.com/golangci/golangci-lint/v2/pkg/goanalysis"
+ "github.com/golangci/golangci-lint/v2/pkg/golinters/internal"
+ "github.com/golangci/golangci-lint/v2/pkg/lint/linter"
+ "github.com/golangci/golangci-lint/v2/pkg/result"
+)
+
+const linterNameV2 = "gomodguard_v2"
+
+func NewV2(settings *config.GoModGuardv2Settings) *goanalysis.Linter {
+ var issues []*goanalysis.Issue
+ var mu sync.Mutex
+
+ processorCfg := &gomodguard.Configuration{}
+ if settings != nil {
+ processorCfg.LocalReplaceDirectives = settings.LocalReplaceDirectives
+
+ for _, allowed := range settings.Allowed {
+ rule := gomodguard.AllowedModule{
+ Module: allowed.Module,
+ MatchType: gomodguard.MatchType(allowed.MatchType),
+ Version: nil,
+ Matcher: nil,
+ }
+
+ if allowed.Version != "" {
+ var err error
+
+ rule.Version, err = semver.NewConstraint(allowed.Version)
+ if err != nil {
+ internal.LinterLogger.Fatalf("gomodguard: invalid constraint: %v", err)
+ }
+ }
+
+ processorCfg.Allowed = append(processorCfg.Allowed, rule)
+ }
+
+ for _, blocked := range settings.Blocked {
+ rule := gomodguard.BlockedModule{
+ Module: blocked.Module,
+ MatchType: gomodguard.MatchType(blocked.MatchType),
+ Recommendations: blocked.Recommendations,
+ Reason: blocked.Reason,
+ }
+
+ if blocked.Version != "" {
+ var err error
+
+ rule.Version, err = semver.NewConstraint(blocked.Version)
+ if err != nil {
+ internal.LinterLogger.Fatalf("gomodguard: invalid constraint: %v", err)
+ }
+ }
+
+ processorCfg.Blocked = append(processorCfg.Blocked, rule)
+ }
+ }
+
+ analyzer := &analysis.Analyzer{
+ Name: linterNameV2,
+ Doc: "Allow and blocklist linter for direct Go module dependencies. " +
+ "This is different from depguard where there are different block " +
+ "types for example version constraints and module recommendations.",
+ Run: goanalysis.DummyRun,
+ }
+
+ return goanalysis.NewLinterFromAnalyzer(analyzer).
+ WithContextSetter(func(lintCtx *linter.Context) {
+ processor, err := gomodguard.NewProcessor(processorCfg)
+ if err != nil {
+ lintCtx.Log.Warnf("running gomodguard failed: %s: if you are not using go modules "+
+ "it is suggested to disable this linter", err)
+ return
+ }
+
+ analyzer.Run = func(pass *analysis.Pass) (any, error) {
+ gomodguardIssues := processor.ProcessFiles(internal.GetGoFileNames(pass))
+
+ mu.Lock()
+ defer mu.Unlock()
+
+ for _, gomodguardIssue := range gomodguardIssues {
+ issues = append(issues, goanalysis.NewIssue(&result.Issue{
+ FromLinter: linterNameV2,
+ Pos: gomodguardIssue.Position,
+ Text: gomodguardIssue.Reason,
+ }, pass))
+ }
+
+ return nil, nil
+ }
+ }).
+ WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue {
+ return issues
+ }).
+ WithLoadMode(goanalysis.LoadModeSyntax)
+}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go
index 7755e4ec..9f98f405 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/govet/govet.go
@@ -28,6 +28,7 @@ import (
"golang.org/x/tools/go/analysis/passes/httpmux"
"golang.org/x/tools/go/analysis/passes/httpresponse"
"golang.org/x/tools/go/analysis/passes/ifaceassert"
+ "golang.org/x/tools/go/analysis/passes/inline"
_ "golang.org/x/tools/go/analysis/passes/inspect" // unused internal analyzer
"golang.org/x/tools/go/analysis/passes/loopclosure"
"golang.org/x/tools/go/analysis/passes/lostcancel"
@@ -83,6 +84,7 @@ var (
httpmux.Analyzer,
httpresponse.Analyzer,
ifaceassert.Analyzer,
+ inline.Analyzer,
loopclosure.Analyzer,
lostcancel.Analyzer,
nilfunc.Analyzer,
@@ -109,7 +111,8 @@ var (
waitgroup.Analyzer,
}
- // https://github.com/golang/go/blob/go1.25.2/src/cmd/vet/main.go#L57-L91
+ // https://github.com/golang/go/blob/go1.26.1/src/cmd/vet/main.go#L63-L99
+ // https://github.com/golang/go/blob/go1.26.1/src/cmd/fix/main.go#L47-L51
defaultAnalyzers = []*analysis.Analyzer{
appends.Analyzer,
asmdecl.Analyzer,
@@ -127,6 +130,7 @@ var (
hostport.Analyzer,
httpresponse.Analyzer,
ifaceassert.Analyzer,
+ inline.Analyzer,
loopclosure.Analyzer,
lostcancel.Analyzer,
nilfunc.Analyzer,
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iface/iface.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iface/iface.go
index 0a4a38ab..03330fda 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iface/iface.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/iface/iface.go
@@ -7,6 +7,7 @@ import (
"github.com/uudashr/iface/opaque"
"github.com/uudashr/iface/unexported"
"github.com/uudashr/iface/unused"
+ "github.com/uudashr/iface/unusedmethod"
"golang.org/x/tools/go/analysis"
"github.com/golangci/golangci-lint/v2/pkg/config"
@@ -29,10 +30,11 @@ func New(settings *config.IfaceSettings) *goanalysis.Linter {
func analyzersFromSettings(settings *config.IfaceSettings) []*analysis.Analyzer {
allAnalyzers := map[string]*analysis.Analyzer{
- "identical": identical.Analyzer,
- "unused": unused.Analyzer,
- "opaque": opaque.Analyzer,
- "unexported": unexported.Analyzer,
+ "identical": identical.Analyzer,
+ "unused": unused.Analyzer,
+ "opaque": opaque.Analyzer,
+ "unexported": unexported.Analyzer,
+ "unusedmethod": unusedmethod.Analyzer,
}
if settings == nil || len(settings.Enable) == 0 {
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go
index 97825c07..6878c01e 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go
@@ -5,6 +5,7 @@ import (
"github.com/golangci/golangci-lint/v2/pkg/config"
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
+ "github.com/golangci/golangci-lint/v2/pkg/golinters/internal"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/modernize"
@@ -16,6 +17,15 @@ func New(settings *config.ModernizeSettings) *goanalysis.Linter {
if settings == nil {
analyzers = modernize.Suite
} else {
+ for _, name := range settings.Disable {
+ switch name {
+ case "fmtappendf":
+ internal.LinterLogger.Warnf("%s has been removed from the modernize suite", name)
+ case "waitgroup":
+ internal.LinterLogger.Warnf("%s has been renamed to 'waitgroupgo'", name)
+ }
+ }
+
for _, analyzer := range modernize.Suite {
if slices.Contains(settings.Disable, analyzer.Name) {
continue
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns/nonamedreturns.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns/nonamedreturns.go
index 4149ef81..0dd71e28 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns/nonamedreturns.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns/nonamedreturns.go
@@ -12,7 +12,8 @@ func New(settings *config.NoNamedReturnsSettings) *goanalysis.Linter {
if settings != nil {
cfg = map[string]any{
- analyzer.FlagReportErrorInDefer: settings.ReportErrorInDefer,
+ analyzer.FlagReportErrorInDefer: settings.ReportErrorInDefer,
+ analyzer.FlagAllowUnusedNamedReturns: settings.AllowUnusedNamedReturns,
}
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go
index f3eac2e0..be052628 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/paralleltest/paralleltest.go
@@ -14,6 +14,7 @@ func New(settings *config.ParallelTestSettings) *goanalysis.Linter {
cfg = map[string]any{
"i": settings.IgnoreMissing,
"ignoremissingsubtests": settings.IgnoreMissingSubtests,
+ "checkcleanup": settings.CheckCleanup,
}
if config.IsGoGreaterThanOrEqual(settings.Go, "1.22") {
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go
index 9dc84537..7fe736f2 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go
@@ -209,9 +209,11 @@ func getConfig(cfg *config.ReviveSettings) (*lint.Config, error) {
}
func createConfigMap(cfg *config.ReviveSettings) map[string]any {
+ const severity = "severity"
+
rawRoot := map[string]any{
"confidence": cfg.Confidence,
- "severity": cfg.Severity,
+ severity: cfg.Severity,
"errorCode": cfg.ErrorCode,
"warningCode": cfg.WarningCode,
"enableAllRules": cfg.EnableAllRules,
@@ -224,7 +226,7 @@ func createConfigMap(cfg *config.ReviveSettings) map[string]any {
rawDirectives := map[string]map[string]any{}
for _, directive := range cfg.Directives {
rawDirectives[directive.Name] = map[string]any{
- "severity": directive.Severity,
+ severity: directive.Severity,
}
}
@@ -235,7 +237,7 @@ func createConfigMap(cfg *config.ReviveSettings) map[string]any {
rawRules := map[string]map[string]any{}
for _, s := range cfg.Rules {
rawRules[s.Name] = map[string]any{
- "severity": s.Severity,
+ severity: s.Severity,
"arguments": safeTomlSlice(s.Arguments),
"disabled": s.Disabled,
"exclude": s.Exclude,
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go
index de0fe4da..57299039 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/rowserrcheck/rowserrcheck.go
@@ -1,7 +1,7 @@
package rowserrcheck
import (
- "github.com/jingyugao/rowserrcheck/passes/rowserr"
+ "github.com/golangci/rowserrcheck/passes/rowserr"
"github.com/golangci/golangci-lint/v2/pkg/config"
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go
index 891f1fcf..2db696e5 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/sloglint/sloglint.go
@@ -7,22 +7,31 @@ import (
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
)
-func New(settings *config.SlogLintSettings) *goanalysis.Linter {
+func New(settings *config.SloglintSettings) *goanalysis.Linter {
var opts *sloglint.Options
if settings != nil {
opts = &sloglint.Options{
- NoMixedArgs: settings.NoMixedArgs,
- KVOnly: settings.KVOnly,
- AttrOnly: settings.AttrOnly,
- NoGlobal: settings.NoGlobal,
- ContextOnly: settings.Context,
- StaticMsg: settings.StaticMsg,
- MsgStyle: settings.MsgStyle,
- NoRawKeys: settings.NoRawKeys,
- KeyNamingCase: settings.KeyNamingCase,
- ForbiddenKeys: settings.ForbiddenKeys,
- ArgsOnSepLines: settings.ArgsOnSepLines,
+ NoGlobalLogger: settings.NoGlobal,
+ ContextOnly: settings.Context,
+ StaticMessage: settings.StaticMsg,
+ MessageStyle: settings.MsgStyle,
+ NoMixedArguments: settings.NoMixedArgs,
+ KeyValuePairsOnly: settings.KVOnly,
+ AttributesOnly: settings.AttrOnly,
+ ArgumentsOnSeparateLines: settings.ArgsOnSepLines,
+ ConstantKeys: settings.NoRawKeys,
+ AllowedKeys: settings.AllowedKeys,
+ ForbiddenKeys: settings.ForbiddenKeys,
+ KeyNamingCase: settings.KeyNamingCase,
+ }
+
+ for _, fn := range settings.CustomFuncs {
+ opts.CustomFuncs = append(opts.CustomFuncs, sloglint.Func{
+ FullName: fn.Name,
+ MessagePos: fn.MsgPos,
+ ArgumentsPos: fn.ArgsPos,
+ })
}
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go
index cb7b2562..8b8eef3f 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/wsl/wsl_v5.go
@@ -18,12 +18,13 @@ func NewV5(settings *config.WSLv5Settings) *goanalysis.Linter {
}
conf = &wsl.Configuration{
- IncludeGenerated: true, // force to true because golangci-lint already has a way to filter generated files.
- AllowFirstInBlock: settings.AllowFirstInBlock,
- AllowWholeBlock: settings.AllowWholeBlock,
- BranchMaxLines: settings.BranchMaxLines,
- CaseMaxLines: settings.CaseMaxLines,
- Checks: checkSet,
+ IncludeGenerated: true, // force to true because golangci-lint already has a way to filter generated files.
+ AllowFirstInBlock: settings.AllowFirstInBlock,
+ AllowWholeBlock: settings.AllowWholeBlock,
+ BranchMaxLines: settings.BranchMaxLines,
+ CaseMaxLines: settings.CaseMaxLines,
+ CuddleMaxStatements: settings.CuddleMaxStatements,
+ Checks: checkSet,
}
}
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go
index a5b98413..2386220d 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/linter/config.go
@@ -185,15 +185,18 @@ func Replacement[T any](replacement string, mgr func(T) any, data T) func(*Depre
encoder := yaml.NewEncoder(buf)
encoder.SetIndent(2)
+ linters := map[string]any{
+ "enable": []string{d.Replacement},
+ }
+
+ replacementSettings := mgr(data)
+
+ if replacementSettings != nil {
+ linters["settings"] = map[string]any{d.Replacement: replacementSettings}
+ }
+
suggestion := map[string]any{
- "linters": map[string]any{
- "enable": []string{
- d.Replacement,
- },
- "settings": map[string]any{
- d.Replacement: mgr(data),
- },
- },
+ "linters": linters,
}
err := encoder.Encode(suggestion)
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go
index 44eadecc..d2b6ac04 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go
@@ -9,6 +9,7 @@ import (
"github.com/golangci/golangci-lint/v2/pkg/golinters/bidichk"
"github.com/golangci/golangci-lint/v2/pkg/golinters/bodyclose"
"github.com/golangci/golangci-lint/v2/pkg/golinters/canonicalheader"
+ "github.com/golangci/golangci-lint/v2/pkg/golinters/clickhouselint"
"github.com/golangci/golangci-lint/v2/pkg/golinters/containedctx"
"github.com/golangci/golangci-lint/v2/pkg/golinters/contextcheck"
"github.com/golangci/golangci-lint/v2/pkg/golinters/copyloopvar"
@@ -161,7 +162,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
WithSince("v1.43.0").
WithURL("https://github.com/breml/bidichk"),
- linter.NewConfig(bodyclose.New()).
+ linter.NewConfig(bodyclose.New(&cfg.Linters.Settings.BodyClose)).
WithSince("v1.18.0").
WithLoadForGoAnalysis().
WithURL("https://github.com/timakin/bodyclose"),
@@ -172,6 +173,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
WithAutoFix().
WithURL("https://github.com/lasiar/canonicalheader"),
+ linter.NewConfig(clickhouselint.New()).
+ WithSince("v2.12.0").
+ WithLoadForGoAnalysis().
+ WithURL("https://github.com/ClickHouse/clickhouse-go-linter"),
+
linter.NewConfig(containedctx.New()).
WithSince("v1.44.0").
WithLoadForGoAnalysis().
@@ -251,6 +257,13 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
linter.NewConfig(exhaustruct.New(&cfg.Linters.Settings.Exhaustruct)).
WithSince("v1.46.0").
+ DeprecatedWarning("new major version.", "v2.13.0",
+ linter.Replacement("exhaustruct_v5", nil, &cfg.Linters.Settings.Exhaustruct)).
+ WithLoadForGoAnalysis().
+ WithURL("https://github.com/GaijinEntertainment/go-exhaustruct"),
+
+ linter.NewConfig(exhaustruct.NewV5(&cfg.Linters.Settings.Exhaustructv5)).
+ WithSince("v2.13.0").
WithLoadForGoAnalysis().
WithURL("https://github.com/GaijinEntertainment/go-exhaustruct"),
@@ -367,7 +380,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
linter.NewConfig(golines.New(&cfg.Linters.Settings.GoLines)).
WithSince("v2.0.0").
WithAutoFix().
- WithURL("https://github.com/segmentio/golines"),
+ WithURL("https://github.com/golangci/golines"),
linter.NewConfig(goheader.New(&cfg.Linters.Settings.Goheader, placeholderReplacer)).
WithSince("v1.28.0").
@@ -385,6 +398,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
linter.NewConfig(modernize.New(&cfg.Linters.Settings.Modernize)).
WithSince("v2.6.0").
+ WithAutoFix().
WithLoadForGoAnalysis().
WithURL("https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize"),
@@ -394,6 +408,12 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
linter.NewConfig(gomodguard.New(&cfg.Linters.Settings.Gomodguard)).
WithSince("v1.25.0").
+ DeprecatedWarning("new major version.", "v2.12.0",
+ linter.Replacement("gomodguard_v2", gomodguard.Migration, &cfg.Linters.Settings.Gomodguard)).
+ WithURL("https://github.com/ryancurrah/gomodguard"),
+
+ linter.NewConfig(gomodguard.NewV2(&cfg.Linters.Settings.Gomodguardv2)).
+ WithSince("v2.12.0").
WithURL("https://github.com/ryancurrah/gomodguard"),
linter.NewConfig(goprintffuncname.New()).
@@ -593,9 +613,9 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
linter.NewConfig(rowserrcheck.New(&cfg.Linters.Settings.RowsErrCheck)).
WithSince("v1.23.0").
WithLoadForGoAnalysis().
- WithURL("https://github.com/jingyugao/rowserrcheck"),
+ WithURL("https://github.com/golangci/rowserrcheck"),
- linter.NewConfig(sloglint.New(&cfg.Linters.Settings.SlogLint)).
+ linter.NewConfig(sloglint.New(&cfg.Linters.Settings.Sloglint)).
WithSince("v1.55.0").
WithLoadForGoAnalysis().
WithAutoFix().
diff --git a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_plugin_go.go b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_plugin_go.go
index 005ca616..61105da4 100644
--- a/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_plugin_go.go
+++ b/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_plugin_go.go
@@ -92,7 +92,9 @@ func (b *PluginGoBuilder) getAnalyzerPlugin(cfg *config.Config, path string, set
path = filepath.Join(basePath, path)
}
+ //nolint:staticcheck,nolintlint // Ignore because the implementation on Windows returns nil
plug, err := plugin.Open(path)
+ //nolint:staticcheck,nolintlint // Ignore because the implementation on Windows returns nil
if err != nil {
return nil, err
}
@@ -106,7 +108,9 @@ func (b *PluginGoBuilder) getAnalyzerPlugin(cfg *config.Config, path string, set
}
func (b *PluginGoBuilder) lookupPlugin(plug *plugin.Plugin, settings any) ([]*analysis.Analyzer, error) {
+ //nolint:staticcheck,nolintlint // Ignore because the implementation on Windows returns nil
symbol, err := plug.Lookup("New")
+ //nolint:staticcheck,nolintlint // Ignore because the implementation on Windows returns nil
if err != nil {
analyzers, errP := b.lookupAnalyzerPlugin(plug)
if errP != nil {
@@ -126,7 +130,9 @@ func (b *PluginGoBuilder) lookupPlugin(plug *plugin.Plugin, settings any) ([]*an
}
func (b *PluginGoBuilder) lookupAnalyzerPlugin(plug *plugin.Plugin) ([]*analysis.Analyzer, error) {
+ //nolint:staticcheck,nolintlint // Ignore because the implementation on Windows returns nil
symbol, err := plug.Lookup("AnalyzerPlugin")
+ //nolint:staticcheck,nolintlint // Ignore because the implementation on Windows returns nil
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/jingyugao/rowserrcheck/LICENSE b/vendor/github.com/golangci/rowserrcheck/LICENSE
similarity index 100%
rename from vendor/github.com/jingyugao/rowserrcheck/LICENSE
rename to vendor/github.com/golangci/rowserrcheck/LICENSE
diff --git a/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go b/vendor/github.com/golangci/rowserrcheck/passes/rowserr/rowserr.go
similarity index 82%
rename from vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go
rename to vendor/github.com/golangci/rowserrcheck/passes/rowserr/rowserr.go
index a142a674..a05382c6 100644
--- a/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go
+++ b/vendor/github.com/golangci/rowserrcheck/passes/rowserr/rowserr.go
@@ -3,6 +3,7 @@ package rowserr
import (
"go/ast"
"go/types"
+ "slices"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/buildssa"
@@ -35,21 +36,22 @@ type runner struct {
sqlPkgs []string
}
-func NewRun(pkgs ...string) func(pass *analysis.Pass) (interface{}, error) {
- return func(pass *analysis.Pass) (interface{}, error) {
- sqlPkgs := append(pkgs, "database/sql")
+func NewRun(pkgs ...string) func(pass *analysis.Pass) (any, error) {
+ return func(pass *analysis.Pass) (any, error) {
+ sqlPkgs := slices.Concat(pkgs, []string{"database/sql"})
for _, pkg := range sqlPkgs {
r := new(runner)
r.sqlPkgs = sqlPkgs
r.run(pass, pkg)
}
+
return nil, nil
}
}
// run executes an analysis for the pass. The receiver is passed
// by value because this func is called in parallel for different passes.
-func (r runner) run(pass *analysis.Pass, pkgPath string) {
+func (r *runner) run(pass *analysis.Pass, pkgPath string) {
r.pass = pass
pssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)
funcs := pssa.SrcFuncs
@@ -65,6 +67,7 @@ func (r runner) run(pass *analysis.Pass, pkgPath string) {
// skip checking
return
}
+
r.rowsObj = rowsType.Object()
if r.rowsObj == nil {
// skip checking
@@ -88,8 +91,8 @@ func (r runner) run(pass *analysis.Pass, pkgPath string) {
// skip if the function is just referenced
var isRefFunc bool
- for i := 0; i < f.Signature.Results().Len(); i++ {
- if types.Identical(f.Signature.Results().At(i).Type(), r.rowsTyp) {
+ for v := range f.Signature.Results().Variables() {
+ if types.Identical(v.Type(), r.rowsTyp) {
isRefFunc = true
}
}
@@ -114,38 +117,59 @@ func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) {
return false
}
+ if call.Referrers() == nil {
+ return false
+ }
+
for _, cRef := range *call.Referrers() {
val, ok := r.getRowsVal(cRef)
if !ok {
continue
}
- if len(*val.Referrers()) == 0 {
- continue
+
+ if val.Referrers() == nil {
+ return false
}
+
resRefs := *val.Referrers()
+
+ if len(resRefs) == 0 {
+ continue
+ }
+
var errCalled func(resRef ssa.Instruction) bool
+
errCalled = func(resRef ssa.Instruction) bool {
switch resRef := resRef.(type) {
case *ssa.Phi:
- for _, rf := range *resRef.Referrers() {
- if errCalled(rf) {
- return true
- }
+ if resRef.Referrers() == nil {
+ return false
+ }
+
+ if slices.ContainsFunc(*resRef.Referrers(), errCalled) {
+ return true
}
case *ssa.Store: // Call in Closure function
+ if resRef.Addr.Referrers() == nil {
+ return false
+ }
+
for _, aref := range *resRef.Addr.Referrers() {
switch c := aref.(type) {
case *ssa.MakeClosure:
f := c.Fn.(*ssa.Function)
+
called := r.isClosureCalled(c)
if r.calledInFunc(f, called) {
return true
}
case *ssa.UnOp:
- for _, rf := range *c.Referrers() {
- if errCalled(rf) {
- return true
- }
+ if c.Referrers() == nil {
+ continue
+ }
+
+ if slices.ContainsFunc(*c.Referrers(), errCalled) {
+ return true
}
}
}
@@ -153,6 +177,7 @@ func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) {
if r.isErrCall(resRef) {
return true
}
+
if f, ok := resRef.Call.Value.(*ssa.Function); ok {
for _, b := range f.Blocks {
for i := range b.Instrs {
@@ -163,16 +188,22 @@ func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) {
}
}
case *ssa.FieldAddr:
+ if resRef.Referrers() == nil {
+ return false
+ }
+
for _, bRef := range *resRef.Referrers() {
bOp, ok := r.getBodyOp(bRef)
if !ok {
continue
}
- for _, ccall := range *bOp.Referrers() {
- if r.isErrCall(ccall) {
- return true
- }
+ if bOp.Referrers() == nil {
+ continue
+ }
+
+ if slices.ContainsFunc(*bOp.Referrers(), r.isErrCall) {
+ return true
}
}
}
@@ -180,10 +211,8 @@ func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) {
return false
}
- for _, resRef := range resRefs {
- if errCalled(resRef) {
- return false
- }
+ if slices.ContainsFunc(resRefs, errCalled) {
+ return false
}
}
@@ -198,11 +227,12 @@ func (r *runner) getCallReturnsRow(instr ssa.Instruction) (*ssa.Call, bool) {
res := call.Call.Signature().Results()
- for i := 0; i < res.Len(); i++ {
- typeToCheck := res.At(i).Type()
+ for v := range res.Variables() {
+ typeToCheck := v.Type()
if types.Identical(typeToCheck, r.rowsTyp) {
return call, true
}
+
if r.rowsInterface != nil && types.Implements(typeToCheck, r.rowsInterface) {
return call, true
}
@@ -217,6 +247,7 @@ func (r *runner) getRowsVal(instr ssa.Instruction) (ssa.Value, bool) {
if len(instr.Call.Args) == 1 && types.Identical(instr.Call.Args[0].Type(), r.rowsTyp) {
return instr.Call.Args[0], true
}
+
if len(instr.Call.Args) == 1 && r.rowsInterface != nil && types.Implements(instr.Call.Args[0].Type(), r.rowsInterface) {
return instr.Call.Args[0], true
}
@@ -224,6 +255,7 @@ func (r *runner) getRowsVal(instr ssa.Instruction) (ssa.Value, bool) {
if types.Identical(instr.Type(), r.rowsTyp) {
return instr, true
}
+
if r.rowsInterface != nil && types.Implements(instr.Type(), r.rowsInterface) {
return instr, true
}
@@ -251,6 +283,7 @@ func (r *runner) isErrCall(ccall ssa.Instruction) bool {
if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod {
return true
}
+
if ccall.Call.Method != nil && ccall.Call.Method.Name() == errMethod {
return true
}
@@ -258,6 +291,7 @@ func (r *runner) isErrCall(ccall ssa.Instruction) bool {
if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod {
return true
}
+
if ccall.Call.Method != nil && ccall.Call.Method.Name() == errMethod {
return true
}
@@ -267,6 +301,10 @@ func (r *runner) isErrCall(ccall ssa.Instruction) bool {
}
func (r *runner) isClosureCalled(c *ssa.MakeClosure) bool {
+ if c.Referrers() == nil {
+ return false
+ }
+
for _, ref := range *c.Referrers() {
switch ref.(type) {
case *ssa.Call, *ssa.Defer:
@@ -282,7 +320,12 @@ func (r *runner) calledInFunc(f *ssa.Function, called bool) bool {
for i, instr := range b.Instrs {
switch instr := instr.(type) {
case *ssa.UnOp:
+ if instr.Referrers() == nil {
+ continue
+ }
+
for _, ref := range *instr.Referrers() {
+ //nolint:nestif // need to be reviewed.
if v, ok := ref.(ssa.Value); ok {
if vCall, ok := v.(*ssa.Call); ok {
if vCall.Call.Value != nil && vCall.Call.Value.Name() == errMethod {
@@ -300,5 +343,6 @@ func (r *runner) calledInFunc(f *ssa.Function, called bool) bool {
}
}
}
+
return false
}
diff --git a/vendor/github.com/hashicorp/go-version/CHANGELOG.md b/vendor/github.com/hashicorp/go-version/CHANGELOG.md
index 6d48174b..81b42315 100644
--- a/vendor/github.com/hashicorp/go-version/CHANGELOG.md
+++ b/vendor/github.com/hashicorp/go-version/CHANGELOG.md
@@ -1,3 +1,41 @@
+# 1.9.0 (Mar 30, 2026)
+
+ENHANCEMENTS:
+
+Support parsing versions with custom prefixes via opt-in option in https://github.com/hashicorp/go-version/pull/79
+
+INTERNAL:
+
+- Bump the github-actions-backward-compatible group across 1 directory with 2 updates in https://github.com/hashicorp/go-version/pull/179
+- Bump the github-actions-breaking group with 4 updates in https://github.com/hashicorp/go-version/pull/180
+- Bump the github-actions-backward-compatible group with 3 updates in https://github.com/hashicorp/go-version/pull/182
+- Update GitHub Actions to trigger on pull requests and update go version in https://github.com/hashicorp/go-version/pull/185
+- Bump actions/upload-artifact from 6.0.0 to 7.0.0 in the github-actions-breaking group across 1 directory in https://github.com/hashicorp/go-version/pull/183
+- Bump the github-actions-backward-compatible group across 1 directory with 2 updates in https://github.com/hashicorp/go-version/pull/186
+
+# 1.8.0 (Nov 28, 2025)
+
+ENHANCEMENTS:
+
+- Add benchmark test for version.String() in https://github.com/hashicorp/go-version/pull/159
+- Bytes implementation in https://github.com/hashicorp/go-version/pull/161
+
+INTERNAL:
+
+- Add CODEOWNERS file in .github/CODEOWNERS in https://github.com/hashicorp/go-version/pull/145
+- Linting in https://github.com/hashicorp/go-version/pull/151
+- Correct typos in comments in https://github.com/hashicorp/go-version/pull/134
+- Migrate GitHub Actions updates from TSCCR to Dependabot in https://github.com/hashicorp/go-version/pull/155
+- Bump the github-actions-backward-compatible group with 2 updates in https://github.com/hashicorp/go-version/pull/157
+- Update doc reference in README in https://github.com/hashicorp/go-version/pull/135
+- Bump the github-actions-breaking group with 3 updates in https://github.com/hashicorp/go-version/pull/156
+- [Compliance] - PR Template Changes Required in https://github.com/hashicorp/go-version/pull/158
+- Bump actions/cache from 4.2.3 to 4.2.4 in the github-actions-backward-compatible group in https://github.com/hashicorp/go-version/pull/167
+- Bump actions/checkout from 4.2.2 to 5.0.0 in the github-actions-breaking group in https://github.com/hashicorp/go-version/pull/166
+- Bump the github-actions-breaking group across 1 directory with 2 updates in https://github.com/hashicorp/go-version/pull/171
+- [IND-4226] [COMPLIANCE] Update Copyright Headers in https://github.com/hashicorp/go-version/pull/172
+- drop init() in https://github.com/hashicorp/go-version/pull/175
+
# 1.7.0 (May 24, 2024)
ENHANCEMENTS:
diff --git a/vendor/github.com/hashicorp/go-version/README.md b/vendor/github.com/hashicorp/go-version/README.md
index 83a8249f..55289602 100644
--- a/vendor/github.com/hashicorp/go-version/README.md
+++ b/vendor/github.com/hashicorp/go-version/README.md
@@ -34,6 +34,32 @@ if v1.LessThan(v2) {
}
```
+#### Version Parsing and Comparison with Prefixes
+
+The library also supports parsing versions with a custom prefix.
+Using the `WithPrefix` option, you can specify a prefix to strip
+before parsing the version.
+
+Use `WithPrefix` when your input strings carry a known release prefix such as
+`deployment-`, `controller-`, etc.
+
+After parsing, the prefix is not part of the canonical version value. This
+means the regular comparison methods such as `Compare`, `LessThan`, `Equal`,
+and `GreaterThan` compare only the stripped version. If you compare versions
+from different prefixes with these methods, the prefixes are ignored. If you
+need to reject cross-prefix comparisons, inspect the parsed prefixes before
+comparing the versions.
+
+```go
+v1, _ := version.NewVersion("deployment-v1.2.3-beta+metadata", version.WithPrefix("deployment-"))
+v2, _ := version.NewVersion("deployment-v1.2.4", version.WithPrefix("deployment-"))
+
+if v1.LessThan(v2) {
+ fmt.Printf("%s (%s) is less than %s (%s)\n", v1, v1.Original(), v2, v2.Original())
+ // Outputs: 1.2.3-beta+metadata (deployment-v1.2.3-beta+metadata) is less than 1.2.4 (deployment-v1.2.4)
+}
+```
+
#### Version Constraints
```go
diff --git a/vendor/github.com/hashicorp/go-version/version.go b/vendor/github.com/hashicorp/go-version/version.go
index 17b29732..b95503d3 100644
--- a/vendor/github.com/hashicorp/go-version/version.go
+++ b/vendor/github.com/hashicorp/go-version/version.go
@@ -49,6 +49,23 @@ const (
`?`
)
+// Optional options for NewVersion function.
+type options struct {
+ // If set, this prefix will be trimmed from the version string before parsing.
+ prefix string
+}
+
+// Option is a functional option for NewVersion.
+type Option func(*options)
+
+// WithPrefix is a functional option that sets a prefix to be removed from the
+// version string before parsing.
+func WithPrefix(prefix string) Option {
+ return func(o *options) {
+ o.prefix = prefix
+ }
+}
+
// Version represents a single version.
type Version struct {
metadata string
@@ -56,12 +73,36 @@ type Version struct {
segments []int64
si int
original string
+ prefix string
}
-// NewVersion parses the given version and returns a new
-// Version.
-func NewVersion(v string) (*Version, error) {
- return newVersion(v, getVersionRegexp())
+// NewVersion parses the given version and returns a new Version.
+//
+// Optional parsing behavior can be enabled with Option values such as
+// WithPrefix, which validates and strips an expected prefix before parsing.
+func NewVersion(v string, opts ...Option) (*Version, error) {
+ options := &options{}
+ for _, opt := range opts {
+ if opt != nil {
+ opt(options)
+ }
+ }
+
+ vToParse := v
+ if options.prefix != "" {
+ if !strings.HasPrefix(v, options.prefix) {
+ return nil, fmt.Errorf("version %q does not have prefix %q", v, options.prefix)
+ }
+ vToParse = strings.TrimPrefix(v, options.prefix)
+ }
+
+ ver, err := newVersion(vToParse, getVersionRegexp())
+ if err != nil {
+ return nil, err
+ }
+ ver.prefix = options.prefix
+ ver.original = v
+ return ver, nil
}
// NewSemver parses the given version and returns a new
@@ -424,6 +465,11 @@ func (v *Version) Original() string {
return v.original
}
+// Prefix returns the explicit prefix used with WithPrefix, if any.
+func (v *Version) Prefix() string {
+ return v.prefix
+}
+
// UnmarshalText implements encoding.TextUnmarshaler interface.
func (v *Version) UnmarshalText(b []byte) error {
temp, err := NewVersion(string(b))
diff --git a/vendor/github.com/jgautheron/goconst/README.md b/vendor/github.com/jgautheron/goconst/README.md
index 727974d0..61f8e781 100644
--- a/vendor/github.com/jgautheron/goconst/README.md
+++ b/vendor/github.com/jgautheron/goconst/README.md
@@ -8,6 +8,16 @@ There are obvious benefits to using constants instead of repeating strings, most
While this could be considered a beginner mistake, across time, multiple packages and large codebases, some repetition could have slipped in.
+### How it works
+
+goconst detects string (and optionally number) literals that appear multiple times and could be replaced by a constant.
+
+A few things to keep in mind:
+
+- **Exact literal matching** — goconst compares complete, unquoted literal values. Repeated substrings inside larger strings are not detected (e.g., a shared prefix across two different string literals will not be reported).
+- **`const` declarations are skipped by default** — constant values are only analyzed when `-match-constant` (match strings against existing constants) or `-find-duplicates` (find constants sharing the same value) is enabled.
+- **String length is measured in runes**, not bytes, so multi-byte Unicode characters are counted correctly against `-min-length`.
+
### Get Started
$ go install github.com/jgautheron/goconst/cmd/goconst@latest
@@ -22,20 +32,23 @@ Usage:
Flags:
- -ignore exclude files matching the given regular expression
- -ignore-strings exclude strings matching the given regular expression
- -ignore-tests exclude tests from the search (default: true)
- -min-occurrences report from how many occurrences (default: 2)
- -min-length only report strings with the minimum given length (default: 3)
- -match-constant look for existing constants matching the strings
- -find-duplicates look for constants with identical values
- -eval-const-expr enable evaluation of constant expressions (e.g., Prefix + "suffix")
- -numbers search also for duplicated numbers
- -min minimum value, only works with -numbers
- -max maximum value, only works with -numbers
- -output output formatting (text or json)
- -set-exit-status Set exit status to 2 if any issues are found
- -grouped print single line per match, only works with -output text
+ -ignore exclude files matching the given regular expression
+ -ignore-strings exclude strings matching the given regular expression
+ -ignore-tests exclude tests from the search (default: true)
+ -min-occurrences report from how many occurrences (default: 2)
+ -min-length only report strings with the minimum given length (default: 3)
+ -match-constant look for existing constants matching the strings
+ -find-duplicates look for constants with identical values
+ -eval-const-expr enable evaluation of constant expressions (e.g., Prefix + "suffix")
+ -ignore-calls ignore string literals in calls to these functions (comma separated)
+ -ignore-composite-literals ignore string literals inside composite literals
+ -ignore-map-keys ignore string literals used as map keys
+ -numbers search also for duplicated numbers
+ -min minimum value, only works with -numbers
+ -max maximum value, only works with -numbers
+ -output output formatting (text or json)
+ -set-exit-status Set exit status to 2 if any issues are found
+ -grouped print single line per match, only works with -output text
Examples:
@@ -45,6 +58,7 @@ Examples:
goconst -numbers -min 60 -max 512 .
goconst -min-occurrences 5 $(go list -m -f '{{.Dir}}')
goconst -eval-const-expr -match-constant . # Matches constant expressions like Prefix + "suffix"
+ goconst -ignore-calls slog.Info,slog.Warn,fmt.Errorf ./... # Ignore strings in logging/error calls
```
### Development
diff --git a/vendor/github.com/jgautheron/goconst/api.go b/vendor/github.com/jgautheron/goconst/api.go
index 10cece15..454108e7 100644
--- a/vendor/github.com/jgautheron/goconst/api.go
+++ b/vendor/github.com/jgautheron/goconst/api.go
@@ -12,6 +12,8 @@ import (
// Issue represents a finding of duplicated strings, numbers, or constants.
// Each Issue includes the position where it was found, how many times it occurs,
// the string itself, and any matching constant name.
+// When both test and non-test files are analyzed, OccurrencesCount reflects
+// the count within the issue's scope (test or non-test) rather than the global total.
type Issue struct {
Pos token.Position
OccurrencesCount int
@@ -45,6 +47,12 @@ type Config struct {
FindDuplicates bool
// EvalConstExpressions enables evaluation of constant expressions like Prefix + "suffix"
EvalConstExpressions bool
+ // IgnoreFunctions is a list of function names whose string arguments should be ignored.
+ // Supports direct calls (e.g., "println") and one-level qualified calls (e.g., "slog.Info").
+ IgnoreFunctions []string
+ // IgnoreMapKeys ignores string literals used as keys in map literals
+ // (e.g., the "key" in map[string]any{"key": "value"}).
+ IgnoreMapKeys bool
}
// NewWithIgnorePatterns creates a new instance of the parser with support for multiple ignore patterns.
@@ -108,6 +116,14 @@ func RunWithConfig(files []*ast.File, fset *token.FileSet, typeInfo *types.Info,
cfg.ExcludeTypes,
)
+ if len(cfg.IgnoreFunctions) > 0 {
+ p.SetIgnoreFunctions(cfg.IgnoreFunctions)
+ }
+
+ if cfg.IgnoreMapKeys {
+ p.SetIgnoreMapKeys(true)
+ }
+
// Pre-allocate slice based on estimated result size
expectedIssues := len(files) * 5 // Assuming average of 5 issues per file
if expectedIssues > 1000 {
@@ -145,13 +161,14 @@ func RunWithConfig(files []*ast.File, fset *token.FileSet, typeInfo *types.Info,
wg.Done()
}()
- // Use empty interned strings for package/file names
- // The visitor logic will set these appropriately
- emptyStr := InternString("")
+ pkgName := ""
+ if f.Name != nil {
+ pkgName = f.Name.Name
+ }
ast.Walk(&treeVisitor{
fileSet: fset,
- packageName: emptyStr,
+ packageName: InternString(pkgName),
p: p,
ignoreRegex: p.ignoreStringsRegex,
typeInfo: typeInfo,
@@ -170,7 +187,8 @@ func RunWithConfig(files []*ast.File, fset *token.FileSet, typeInfo *types.Info,
// Create a slice to hold the string keys
stringKeys := make([]string, 0, len(p.strs))
- // Create an array of strings to sort for stable output
+ // Global count is a coarse prefilter; the reporting loop below
+ // re-applies minOccurrences per scope (test vs non-test).
for str := range p.strs {
if count := p.stringCount[str]; count >= p.minOccurrences {
stringKeys = append(stringKeys, str)
@@ -179,69 +197,127 @@ func RunWithConfig(files []*ast.File, fset *token.FileSet, typeInfo *types.Info,
sort.Strings(stringKeys)
- // Process strings in a predictable order for stable output
+ // Emit one issue per file where the string appears, so that
+ // path-based exclusion can independently filter each one without
+ // suppressing legitimate findings in other files.
+ // Occurrence counts are scoped: test-file issues report test-file
+ // counts and non-test issues report non-test counts, preventing
+ // test-file occurrences from inflating production-file reports.
for _, str := range stringKeys {
- positions := p.strs[str]
+ // Copy positions so the sort does not mutate the map value
+ // under the read lock.
+ positions := append([]ExtendedPos(nil), p.strs[str]...)
if len(positions) == 0 {
continue
}
- // Use the first position as representative
- fi := positions[0]
+ sortPositions(positions)
- // Create issue using the counted value to avoid recounting
- issue := Issue{
- Pos: fi.Position,
- OccurrencesCount: p.stringCount[str],
- Str: str,
+ var nonTestCount, testCount int
+ for _, pos := range positions {
+ if strings.HasSuffix(pos.Filename, testSuffix) {
+ testCount++
+ } else {
+ nonTestCount++
+ }
}
- // Check for matching constants
- if len(p.consts) > 0 {
+ // Resolve matching constants per scope so that non-test issues
+ // never reference test-only constants (which production code
+ // cannot use). Test issues may reference any constant.
+ // Only resolve when MatchWithConstants is enabled; FindDuplicates
+ // also populates p.consts but should not affect string issues.
+ var anyMatchingConst, nonTestMatchingConst string
+ if p.matchConstant {
p.constMutex.RLock()
- if csts, ok := p.consts[str]; ok && len(csts) > 0 {
- // const should be in the same package and exported
- issue.MatchingConst = csts[0].Name
- }
+ raw := p.consts[str]
p.constMutex.RUnlock()
+
+ if len(raw) > 0 {
+ // Copy so the sort does not mutate the map value.
+ csts := append([]ConstType(nil), raw...)
+ sortConstants(csts)
+ anyMatchingConst = csts[0].Name
+ for _, cst := range csts {
+ if !strings.HasSuffix(cst.Filename, testSuffix) {
+ nonTestMatchingConst = cst.Name
+ break
+ }
+ }
+ }
}
- issueBuffer = append(issueBuffer, issue)
- }
+ seen := make(map[string]bool)
+ for _, pos := range positions {
+ if seen[pos.Filename] {
+ continue
+ }
+ seen[pos.Filename] = true
- p.stringCountMutex.RUnlock()
- p.stringMutex.RUnlock()
+ isTest := strings.HasSuffix(pos.Filename, testSuffix)
- // process duplicate constants
- p.constMutex.RLock()
+ scopeCount := nonTestCount
+ if isTest {
+ scopeCount = testCount
+ }
- // Create a new slice for const keys
- stringKeys = make([]string, 0, len(p.consts))
+ if scopeCount < p.minOccurrences {
+ continue
+ }
- // Create an array of strings and sort for stable output
- for str := range p.consts {
- if len(p.consts[str]) > 1 {
- stringKeys = append(stringKeys, str)
+ matchingConst := nonTestMatchingConst
+ if isTest && matchingConst == "" {
+ matchingConst = anyMatchingConst
+ }
+
+ issueBuffer = append(issueBuffer, Issue{
+ Pos: pos.Position,
+ OccurrencesCount: scopeCount,
+ Str: str,
+ MatchingConst: matchingConst,
+ })
}
}
- sort.Strings(stringKeys)
+ p.stringCountMutex.RUnlock()
+ p.stringMutex.RUnlock()
- // report an issue for every duplicated const
- for _, str := range stringKeys {
- positions := p.consts[str]
+ // Process duplicate constants only when explicitly requested.
+ // p.consts may also be populated by matchConstant for constant
+ // matching, but those extra entries should not trigger duplicate reports.
+ if p.findDuplicates {
+ p.constMutex.RLock()
+
+ // Report an issue for every duplicated const within the same scope.
+ // Test and non-test constants are compared independently so that a
+ // test constant is never flagged as duplicate of a production one.
+ for _, group := range duplicateConstGroups(p.consts) {
+ allConsts := group.consts
+
+ var nonTestConsts, testConsts []ConstType
+ for _, cst := range allConsts {
+ if strings.HasSuffix(cst.Filename, testSuffix) {
+ testConsts = append(testConsts, cst)
+ } else {
+ nonTestConsts = append(nonTestConsts, cst)
+ }
+ }
- for i := 1; i < len(positions); i++ {
- issueBuffer = append(issueBuffer, Issue{
- Pos: positions[i].Position,
- Str: str,
- DuplicateConst: positions[0].Name,
- DuplicatePos: positions[0].Position,
- })
+ for _, scopeConsts := range [][]ConstType{nonTestConsts, testConsts} {
+ sortConstants(scopeConsts)
+ for i := 1; i < len(scopeConsts); i++ {
+ issueBuffer = append(issueBuffer, Issue{
+ Pos: scopeConsts[i].Position,
+ Str: group.displayValue,
+ DuplicateConst: scopeConsts[0].Name,
+ DuplicatePos: scopeConsts[0].Position,
+ })
+ }
+ }
}
- }
- p.constMutex.RUnlock()
+ p.constMutex.RUnlock()
+ }
// Don't return the buffer to pool as the caller now owns it
return issueBuffer, nil
@@ -253,3 +329,63 @@ func RunWithConfig(files []*ast.File, fset *token.FileSet, typeInfo *types.Info,
func Run(files []*ast.File, fset *token.FileSet, typeInfo *types.Info, cfg *Config) ([]Issue, error) {
return RunWithConfig(files, fset, typeInfo, cfg)
}
+
+func lessPosition(a, b token.Position) bool {
+ if a.Filename != b.Filename {
+ return a.Filename < b.Filename
+ }
+ if a.Line != b.Line {
+ return a.Line < b.Line
+ }
+ return a.Column < b.Column
+}
+
+func sortPositions(positions []ExtendedPos) {
+ sort.Slice(positions, func(i, j int) bool {
+ return lessPosition(positions[i].Position, positions[j].Position)
+ })
+}
+
+func sortConstants(consts []ConstType) {
+ sort.Slice(consts, func(i, j int) bool {
+ return lessPosition(consts[i].Position, consts[j].Position)
+ })
+}
+
+type duplicateConstGroup struct {
+ displayValue string
+ consts []ConstType
+}
+
+func duplicateConstGroups(consts Constants) []duplicateConstGroup {
+ groups := make(map[string]duplicateConstGroup, len(consts))
+ for displayValue, values := range consts {
+ for _, cst := range values {
+ key := cst.ValueKey()
+ if key == "" {
+ key = displayValue
+ }
+
+ group := groups[key]
+ if group.displayValue == "" || displayValue < group.displayValue {
+ group.displayValue = displayValue
+ }
+ group.consts = append(group.consts, cst)
+ groups[key] = group
+ }
+ }
+
+ keys := make([]string, 0, len(groups))
+ for key, group := range groups {
+ if len(group.consts) > 1 {
+ keys = append(keys, key)
+ }
+ }
+ sort.Strings(keys)
+
+ result := make([]duplicateConstGroup, 0, len(keys))
+ for _, key := range keys {
+ result = append(result, groups[key])
+ }
+ return result
+}
diff --git a/vendor/github.com/jgautheron/goconst/parser.go b/vendor/github.com/jgautheron/goconst/parser.go
index 9505d463..25e267a5 100644
--- a/vendor/github.com/jgautheron/goconst/parser.go
+++ b/vendor/github.com/jgautheron/goconst/parser.go
@@ -120,6 +120,8 @@ type Parser struct {
minLength, minOccurrences int
numberMin, numberMax int
excludeTypes map[Type]bool
+ ignoreFunctions map[string]struct{}
+ ignoreMapKeys bool // Whether to ignore string literals used as map keys
maxConcurrency int
evalConstExpressions bool // Whether to evaluate constant expressions
@@ -264,6 +266,30 @@ func (p *Parser) EnableBatchProcessing(batchSize int) {
}
}
+// SetIgnoreFunctions configures which function calls should have their string
+// arguments ignored. Supports direct calls (e.g., "println") and one-level
+// qualified calls (e.g., "slog.Info", "fmt.Errorf").
+func (p *Parser) SetIgnoreFunctions(names []string) {
+ if len(names) == 0 {
+ p.ignoreFunctions = nil
+ return
+ }
+ m := make(map[string]struct{}, len(names))
+ for _, name := range names {
+ name = strings.TrimSpace(name)
+ if name != "" {
+ m[name] = struct{}{}
+ }
+ }
+ p.ignoreFunctions = m
+}
+
+// SetIgnoreMapKeys configures whether string literals used as keys in map
+// literals should be ignored. The corresponding values are still reported.
+func (p *Parser) SetIgnoreMapKeys(ignore bool) {
+ p.ignoreMapKeys = ignore
+}
+
// ParseTree will search the given path for occurrences that could be moved into constants.
// If "..." is appended, the search will be recursive.
//
@@ -308,6 +334,7 @@ func (p *Parser) parseTreeConcurrent(rootPath string, recursive bool) (Strings,
// run type checker
info := &types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
+ Defs: make(map[*ast.Ident]types.Object),
}
chkConfig := &types.Config{
@@ -419,6 +446,7 @@ func (p *Parser) parseTreeConcurrent(rootPath string, recursive bool) (Strings,
// Type checking must be performed serially to avoid data races.
info := &types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
+ Defs: make(map[*ast.Ident]types.Object),
}
chkConfig := &types.Config{
@@ -665,6 +693,7 @@ func (p *Parser) parseTreeBatched(rootPath string, recursive bool) (Strings, Con
// Type check -- must be processed serially to avoid data races
info := &types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
+ Defs: make(map[*ast.Ident]types.Object),
}
chkConfig := &types.Config{
@@ -855,6 +884,13 @@ type ConstType struct {
// Interned strings to reduce memory usage
Name string
packageName string
+ valueKey string
+}
+
+// ValueKey returns the internal comparison key used to distinguish constants
+// whose display values may be approximate, such as high-precision numbers.
+func (c ConstType) ValueKey() string {
+ return c.valueKey
}
// ExtendedPos extends token.Position with package information.
@@ -881,4 +917,7 @@ const (
Return
// Call represents a string passed as an argument to a function call (e.g., f("foo"))
Call
+ // CompositeLit represents a string inside a composite literal
+ // (e.g., []string{"foo"}, map[string]string{"k": "v"}, MyStruct{Field: "foo"})
+ CompositeLit
)
diff --git a/vendor/github.com/jgautheron/goconst/visitor.go b/vendor/github.com/jgautheron/goconst/visitor.go
index 350e3ae6..4c3fba69 100644
--- a/vendor/github.com/jgautheron/goconst/visitor.go
+++ b/vendor/github.com/jgautheron/goconst/visitor.go
@@ -8,6 +8,7 @@ import (
"regexp"
"strconv"
"strings"
+ "unicode/utf8"
)
// treeVisitor is used to walk the AST and find strings that could be constants.
@@ -17,6 +18,12 @@ type treeVisitor struct {
packageName string
p *Parser
ignoreRegex *regexp.Regexp
+
+ // skipNodes holds map-key expression subtrees to skip entirely while
+ // walking, used by -ignore-map-keys for keys that are not plain literals
+ // (e.g. NamedString("key")). Populated per file; the walk is single
+ // threaded so no synchronization is needed.
+ skipNodes map[ast.Node]struct{}
}
// Visit browses the AST tree for strings that could be potentially
@@ -27,6 +34,12 @@ func (v *treeVisitor) Visit(node ast.Node) ast.Visitor {
return v
}
+ // Prune map-key expression subtrees flagged by -ignore-map-keys so their
+ // string literals are never recorded (e.g. the "key" in K("key")).
+ if _, skip := v.skipNodes[node]; skip {
+ return nil
+ }
+
// A single case with "ast.BasicLit" would be much easier
// but then we wouldn't be able to tell in which context
// the string is defined (could be a constant definition).
@@ -42,21 +55,42 @@ func (v *treeVisitor) Visit(node ast.Node) ast.Visitor {
for _, spec := range t.Specs {
val := spec.(*ast.ValueSpec)
+ if v.typeInfo != nil && v.p.evalConstExpressions {
+ if len(v.typeInfo.Defs) > 0 {
+ addedFromDefs := false
+ for _, name := range val.Names {
+ obj, ok := v.typeInfo.Defs[name].(*types.Const)
+ if !ok || obj.Val() == nil || !v.isSupportedKind(obj.Val().Kind()) {
+ continue
+ }
+
+ displayValue, valueKey := constValueStrings(obj.Val())
+ v.addConst(name.Name, displayValue, name.Pos(), valueKey)
+ addedFromDefs = true
+ }
+ if addedFromDefs || len(val.Values) == 0 {
+ continue
+ }
+ }
+ }
+
for i, str := range val.Values {
if v.typeInfo != nil && v.p.evalConstExpressions {
typedVal, ok := v.typeInfo.Types[str]
- if !ok || !v.isSupportedKind(typedVal.Value.Kind()) {
+ if !ok || typedVal.Value == nil || !v.isSupportedKind(typedVal.Value.Kind()) {
continue
}
- v.addConst(val.Names[i].Name, typedVal.Value.String(), str.Pos())
- } else {
- lit, ok := str.(*ast.BasicLit)
- if !ok || !v.isSupported(lit.Kind) {
- continue
- }
- v.addConst(val.Names[i].Name, lit.Value, val.Names[i].Pos())
+ displayValue, valueKey := constValueStrings(typedVal.Value)
+ v.addConst(val.Names[i].Name, displayValue, str.Pos(), valueKey)
+ continue
}
+
+ lit, ok := str.(*ast.BasicLit)
+ if !ok || !v.isSupported(lit.Kind) {
+ continue
+ }
+ v.addConst(val.Names[i].Name, lit.Value, val.Names[i].Pos())
}
}
@@ -110,17 +144,115 @@ func (v *treeVisitor) Visit(node ast.Node) ast.Visitor {
// fn("http://")
case *ast.CallExpr:
- for _, item := range t.Args {
- lit, ok := item.(*ast.BasicLit)
- if ok && v.isSupported(lit.Kind) {
- v.addString(lit.Value, lit.Pos(), Call)
+ if !v.shouldIgnoreCall(t) {
+ for _, item := range t.Args {
+ lit, ok := item.(*ast.BasicLit)
+ if ok && v.isSupported(lit.Kind) {
+ v.addString(lit.Value, lit.Pos(), Call)
+ }
}
}
+
+ // []string{"foo"}, map[string]string{"k": "v"}, struct{A string}{A: "foo"}
+ case *ast.CompositeLit:
+ // isMap is only consulted for pruning expression keys, which matters
+ // only when -ignore-map-keys is set.
+ isMap := false
+ if v.p.ignoreMapKeys {
+ isMap = v.isMapLiteral(t)
+ }
+ for _, item := range t.Elts {
+ v.addCompositeLiteralElement(item, isMap)
+ }
}
return v
}
+func constValueStrings(val constant.Value) (string, string) {
+ if val.Kind() == constant.String {
+ return val.ExactString(), "string:" + constant.StringVal(val)
+ }
+ return val.String(), val.Kind().String() + ":" + val.ExactString()
+}
+
+// isMapLiteral reports whether a composite literal is a map. It prefers type
+// information (which resolves named map types and elided nested literals) and
+// falls back to the syntactic type when none is available (e.g. the CLI path,
+// where only explicit map[...]... literals can be recognized).
+func (v *treeVisitor) isMapLiteral(t *ast.CompositeLit) bool {
+ if v.typeInfo != nil {
+ if tv, ok := v.typeInfo.Types[t]; ok && tv.Type != nil {
+ _, isMap := tv.Type.Underlying().(*types.Map)
+ return isMap
+ }
+ }
+ _, ok := t.Type.(*ast.MapType)
+ return ok
+}
+
+func (v *treeVisitor) addCompositeLiteralElement(node ast.Expr, isMap bool) {
+ if lit, ok := node.(*ast.BasicLit); ok && v.isSupported(lit.Kind) {
+ v.addString(lit.Value, lit.Pos(), CompositeLit)
+ return
+ }
+
+ kv, ok := node.(*ast.KeyValueExpr)
+ if !ok {
+ return
+ }
+
+ if keyLit, ok := kv.Key.(*ast.BasicLit); ok {
+ // Direct literal key. A string literal can only be a map key (struct
+ // keys are identifiers, array indices are integers), so it is dropped
+ // when requested with no type information; numeric keys are out of
+ // scope and kept.
+ if v.isSupported(keyLit.Kind) && (!v.p.ignoreMapKeys || keyLit.Kind != token.STRING) {
+ v.addString(keyLit.Value, keyLit.Pos(), CompositeLit)
+ }
+ } else if v.p.ignoreMapKeys && isMap {
+ // Key is an expression (e.g. NamedString("key")); any string literal it
+ // contains is part of the map key, so skip the whole subtree. Gated on
+ // isMap so array indices such as [10]int{int(2): 1} are left alone.
+ v.markSkip(kv.Key)
+ }
+
+ if valueLit, ok := kv.Value.(*ast.BasicLit); ok && v.isSupported(valueLit.Kind) {
+ v.addString(valueLit.Value, valueLit.Pos(), CompositeLit)
+ }
+}
+
+// markSkip flags an AST node so the walk prunes it and its subtree.
+func (v *treeVisitor) markSkip(node ast.Node) {
+ if v.skipNodes == nil {
+ v.skipNodes = make(map[ast.Node]struct{})
+ }
+ v.skipNodes[node] = struct{}{}
+}
+
+// shouldIgnoreCall returns true if the call expression matches a function
+// name in the ignoreFunctions set. Supports direct calls (e.g., "println")
+// and one-level qualified calls (e.g., "slog.Info").
+func (v *treeVisitor) shouldIgnoreCall(call *ast.CallExpr) bool {
+ if len(v.p.ignoreFunctions) == 0 {
+ return false
+ }
+ var name string
+ switch fn := call.Fun.(type) {
+ case *ast.Ident:
+ name = fn.Name
+ case *ast.SelectorExpr:
+ if ident, ok := fn.X.(*ast.Ident); ok {
+ name = ident.Name + "." + fn.Sel.Name
+ }
+ }
+ if name == "" {
+ return false
+ }
+ _, found := v.p.ignoreFunctions[name]
+ return found
+}
+
// addString adds a string in the map along with its position in the tree.
func (v *treeVisitor) addString(str string, pos token.Pos, typ Type) {
// Early type exclusion check
@@ -153,7 +285,7 @@ func (v *treeVisitor) addString(str string, pos token.Pos, typ Type) {
}
// Early length check
- if len(unquotedStr) == 0 || len(unquotedStr) < v.p.minLength {
+ if len(unquotedStr) == 0 || utf8.RuneCountInString(unquotedStr) < v.p.minLength {
return
}
@@ -175,33 +307,25 @@ func (v *treeVisitor) addString(str string, pos token.Pos, typ Type) {
// Use interned string to reduce memory usage - identical strings share the same memory
internedStr := InternString(unquotedStr)
- // Update the count first, this is faster than appending to slices
- count := v.p.IncrementStringCount(internedStr)
+ // Update the count for fast threshold checks in ProcessResults
+ v.p.IncrementStringCount(internedStr)
- // Only continue if we're still adding the position to the map
- // or if count has reached threshold
- if count == 1 || count == v.p.minOccurrences {
- // Lock to safely update the shared map
- v.p.stringMutex.Lock()
- defer v.p.stringMutex.Unlock()
+ // Record every occurrence so that position lists and display counts stay accurate
+ v.p.stringMutex.Lock()
+ defer v.p.stringMutex.Unlock()
- _, exists := v.p.strs[internedStr]
- if !exists {
- v.p.strs[internedStr] = make([]ExtendedPos, 0, v.p.minOccurrences) // Preallocate with expected size
- }
-
- // Create an optimized position record
- newPos := ExtendedPos{
- packageName: InternString(v.packageName), // Intern the package name to reduce memory
- Position: v.fileSet.Position(pos),
- }
-
- v.p.strs[internedStr] = append(v.p.strs[internedStr], newPos)
+ if _, exists := v.p.strs[internedStr]; !exists {
+ v.p.strs[internedStr] = make([]ExtendedPos, 0, v.p.minOccurrences)
}
+
+ v.p.strs[internedStr] = append(v.p.strs[internedStr], ExtendedPos{
+ packageName: InternString(v.packageName),
+ Position: v.fileSet.Position(pos),
+ })
}
// addConst adds a const in the map along with its position in the tree.
-func (v *treeVisitor) addConst(name string, val string, pos token.Pos) {
+func (v *treeVisitor) addConst(name string, val string, pos token.Pos, valueKey ...string) {
// Early filtering using the same criteria as for strings
var unquotedVal string
if strings.HasPrefix(val, `"`) || strings.HasPrefix(val, "`") {
@@ -224,7 +348,7 @@ func (v *treeVisitor) addConst(name string, val string, pos token.Pos) {
}
// Skip constants with values that would be filtered anyway
- if len(unquotedVal) < v.p.minLength {
+ if utf8.RuneCountInString(unquotedVal) < v.p.minLength {
return
}
@@ -236,16 +360,23 @@ func (v *treeVisitor) addConst(name string, val string, pos token.Pos) {
internedVal := InternString(unquotedVal)
internedName := InternString(name)
internedPkg := InternString(v.packageName)
+ internedKey := internedVal
+ if len(valueKey) > 0 && valueKey[0] != "" {
+ internedKey = InternString(valueKey[0])
+ }
// Lock to safely update the shared map
v.p.constMutex.Lock()
defer v.p.constMutex.Unlock()
- // track this const if this is a new const, or if we are searching for duplicate consts
- if _, ok := v.p.consts[internedVal]; !ok || v.p.findDuplicates {
+ // Collect the constant when it is the first with this value, when
+ // duplicate detection needs all of them, or when constant matching
+ // needs all of them to pick the best per scope.
+ if _, ok := v.p.consts[internedVal]; !ok || v.p.findDuplicates || v.p.matchConstant {
v.p.consts[internedVal] = append(v.p.consts[internedVal], ConstType{
Name: internedName,
packageName: internedPkg,
+ valueKey: internedKey,
Position: v.fileSet.Position(pos),
})
}
diff --git a/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go b/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go
index 325aeec9..05e91955 100644
--- a/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go
+++ b/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go
@@ -262,7 +262,7 @@ type visitor struct {
// If the call does not include a selector (like if it is a plain "f()" function call)
// then the final return value will be false.
func (v *visitor) selectorAndFunc(call *ast.CallExpr) (*ast.SelectorExpr, *types.Func, bool) {
- sel, ok := call.Fun.(*ast.SelectorExpr)
+ sel, ok := baseCallExpr(call.Fun).(*ast.SelectorExpr)
if !ok {
return nil, nil, false
}
@@ -420,14 +420,15 @@ func (v *visitor) ignoreCall(call *ast.CallExpr) bool {
// Currently only supports simple expressions:
// 1. f()
// 2. x.y.f()
+ // 3. x.y[T]() or x.y[T1, T2]()
var id *ast.Ident
- switch exp := call.Fun.(type) {
+ switch exp := baseCallExpr(call.Fun).(type) {
case *ast.Ident:
id = exp
case *ast.SelectorExpr:
id = exp.Sel
default:
- // eg: *ast.SliceExpr, *ast.IndexExpr
+ // eg: *ast.SliceExpr
}
if id == nil {
@@ -450,6 +451,24 @@ func (v *visitor) ignoreCall(call *ast.CallExpr) bool {
return false
}
+// baseCallExpr returns the underlying function expression for a call. Type
+// arguments and parentheses wrap the selector/name in additional AST nodes, so
+// matching call.Fun directly would miss forms like errors.AsType[T](err).
+func baseCallExpr(fun ast.Expr) ast.Expr {
+ for {
+ switch f := fun.(type) {
+ case *ast.IndexExpr:
+ fun = f.X
+ case *ast.IndexListExpr:
+ fun = f.X
+ case *ast.ParenExpr:
+ fun = f.X
+ default:
+ return fun
+ }
+ }
+}
+
// nonVendoredPkgPath returns the unvendored version of the provided package
// path (or returns the provided path if it does not represent a vendored
// path).
diff --git a/vendor/github.com/kisielk/errcheck/errcheck/excludes.go b/vendor/github.com/kisielk/errcheck/errcheck/excludes.go
index 3e28a2fd..1ccc631f 100644
--- a/vendor/github.com/kisielk/errcheck/errcheck/excludes.go
+++ b/vendor/github.com/kisielk/errcheck/errcheck/excludes.go
@@ -50,6 +50,9 @@ var DefaultExcludedSymbols = []string{
// hash
"(hash.Hash).Write",
+ "(*crypto/sha3.SHA3).Write",
+ "(*crypto/sha3.SHAKE).Read",
+ "(*crypto/sha3.SHAKE).Write",
// hash/maphash
"(*hash/maphash.Hash).Write",
diff --git a/vendor/github.com/ldez/gomoddirectives/.golangci.yml b/vendor/github.com/ldez/gomoddirectives/.golangci.yml
index 8eb11ff0..90c529bf 100644
--- a/vendor/github.com/ldez/gomoddirectives/.golangci.yml
+++ b/vendor/github.com/ldez/gomoddirectives/.golangci.yml
@@ -29,6 +29,7 @@ linters:
- varnamelen
- wrapcheck
- wsl # deprecated
+ - gomodguard # deprecated
settings:
depguard:
@@ -51,6 +52,7 @@ linters:
goconst:
min-len: 3
min-occurrences: 3
+ ignore-tests: true
gocritic:
disabled-checks:
- sloppyReassign
diff --git a/vendor/github.com/ldez/gomoddirectives/gomoddirectives.go b/vendor/github.com/ldez/gomoddirectives/gomoddirectives.go
index ae416c17..32c7b8d9 100644
--- a/vendor/github.com/ldez/gomoddirectives/gomoddirectives.go
+++ b/vendor/github.com/ldez/gomoddirectives/gomoddirectives.go
@@ -52,6 +52,7 @@ func (r Result) String() string {
// Options the analyzer options.
type Options struct {
+ ReplaceAllowAll bool
ReplaceAllowList []string
ReplaceAllowLocal bool
ExcludeForbidden bool
@@ -252,6 +253,10 @@ func checkReplaceDirectives(file *modfile.File, opts Options) []Result {
}
func checkReplaceDirective(opts Options, r *modfile.Replace) string {
+ if opts.ReplaceAllowAll {
+ return ""
+ }
+
if isLocal(r) {
if opts.ReplaceAllowLocal {
return ""
diff --git a/vendor/github.com/ldez/gomoddirectives/readme.md b/vendor/github.com/ldez/gomoddirectives/readme.md
index 52c6a4cb..ea37304c 100644
--- a/vendor/github.com/ldez/gomoddirectives/readme.md
+++ b/vendor/github.com/ldez/gomoddirectives/readme.md
@@ -26,7 +26,11 @@ linters:
# Default: []
replace-allow-list:
- launchpad.net/gocheck
-
+
+ # Allow all `replace` directives.
+ # Default: false
+ replace-allow-all: true
+
# Allow to not explain why the version has been retracted in the `retract` directives.
# Default: false
retract-allow-no-explanation: true
@@ -85,6 +89,8 @@ Flags:
List of allowed replace directives
-local
Allow local replace directives
+ -all-replace
+ Allow all replace directives
-retract-no-explanation
Allow to use retract directives without explanation
-tool
@@ -120,6 +126,7 @@ retract (
- Ban all `replace` directives.
- Allow only local `replace` directives.
- Allow only some `replace` directives.
+- Allow all `replace` directives.
- Detect duplicated `replace` directives.
- Detect identical `replace` directives.
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md b/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md
index 84f9c7b2..f349b335 100644
--- a/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md
+++ b/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md
@@ -6,8 +6,42 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
The format of this file is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
but only releases after v1.0.3 properly adhere to it.
+## [Unreleased]
+
+## [1.4.1] - 2026-08-02
+### Fixed
+- Corrected `D50ToD65` to use the CSS Color 4 matrix inverse of `D65ToD50` (#85).
+
+## [1.4.0] - 2026-03-28
+### Added
+- Constructors, decomposers, and blend functions for the CSS Color Level 4 wide-gamut RGB color spaces `DisplayP3`, `A98Rgb`, `ProPhotoRgb`, and `Rec2020` (#81)
+- `XyzD50`, `Color.XyzD50`, `D50ToD65`, and `D65ToD50` for working with D50-based color spaces (#81)
+- `HexColor` now implements `fmt.Stringer`
+
+## [1.3.0] - 2025-09-08
+### Added
+- `BlendLinearRgb` (#50)
+- `DistanceRiemersma` (#52)
+- Introduce a function for sorting colors (#57)
+- YAML marshal/unmarshal support (#63)
+- Add support for OkLab and OkLch (#66)
+- Functions that use randomness now support specifying a custom source (#73)
+- Functions BlendOkLab and BlendOkLch (#70)
+
+## Changed
+- `Hex()` parsing is much faster (#78). However, it doesn't tolerate hex codes with alpha anymore (previously ignoring the alpha was unintentional).
+
+### Fixed
+- Fix bug when doing HSV/HCL blending between a gray color and non-gray color (#60)
+- Docs for HSV/HSL were updated to note that hue 360 is not allowed (#71)
+
+### Deprecated
+- `DistanceLinearRGB` is deprecated for the name `DistanceLinearRgb` which is more in-line with the rest of the library
+
## [1.2.0] - 2021-01-27
+This is the same as the v1.1.0 tag.
+
### Added
- HSLuv and HPLuv color spaces (#41, #51)
- CIE LCh(uv) color space, called `LuvLCh` in code (#51)
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/README.md b/vendor/github.com/lucasb-eyer/go-colorful/README.md
index 8b9bd499..1da19f70 100644
--- a/vendor/github.com/lucasb-eyer/go-colorful/README.md
+++ b/vendor/github.com/lucasb-eyer/go-colorful/README.md
@@ -1,6 +1,7 @@
go-colorful
===========
+[](https://pkg.go.dev/github.com/lucasb-eyer/go-colorful)
[](https://goreportcard.com/report/github.com/lucasb-eyer/go-colorful)
A library for playing with colors in Go. Supports Go 1.13 onwards.
@@ -29,10 +30,12 @@ Go-Colorful stores colors in RGB and provides methods from converting these to v
- **CIE-xyY:** encodes chromacity in x and y and luminance in Y, all in [0..1]
- **CIE-L\*a\*b\*:** A *perceptually uniform* color space, i.e. distances are meaningful. L\* in [0..1] and a\*, b\* almost in [-1..1].
- **CIE-L\*u\*v\*:** Very similar to CIE-L\*a\*b\*, there is [no consensus](http://en.wikipedia.org/wiki/CIELUV#Historical_background) on which one is "better".
-- **CIE-L\*C\*h° (HCL):** This is generally the [most useful](http://vis4.net/blog/posts/avoid-equidistant-hsv-colors/) one; CIE-L\*a\*b\* space in polar coordinates, i.e. a *better* HSV. H° is in [0..360], C\* almost in [-1..1] and L\* as in CIE-L\*a\*b\*.
-- **CIE LCh(uv):** Called `LuvLCh` in code, this is a cylindrical transformation of the CIE-L\*u\*v\* color space. Like HCL above: H° is in [0..360], C\* almost in [-1..1] and L\* as in CIE-L\*u\*v\*.
+- **CIE-L\*C\*h° (HCL):** This is generally the [most useful](http://vis4.net/blog/posts/avoid-equidistant-hsv-colors/) one; CIE-L\*a\*b\* space in polar coordinates, i.e. a *better* HSV. H° is in [0..360], C\* almost in [0..1] and L\* as in CIE-L\*a\*b\*.
+- **CIE LCh(uv):** Called `LuvLCh` in code, this is a cylindrical transformation of the CIE-L\*u\*v\* color space. Like HCL above: H° is in [0..360], C\* almost in [0..1] and L\* as in CIE-L\*u\*v\*.
- **HSLuv:** The better alternative to HSL, see [here](https://www.hsluv.org/) and [here](https://www.kuon.ch/post/2020-03-08-hsluv/). Hue in [0..360], Saturation and Luminance in [0..1].
-- **HPLuv:** A variant of HSLuv. The color space is smoother, but only pastel colors can be included. Because the valid colors are limited, it's easy to get invalid Saturation values way above 1.0, indicating the color can't be represented in HPLuv beccause it's not pastel.
+- **HPLuv:** A variant of HSLuv. The color space is smoother, but only pastel colors can be included. Because the valid colors are limited, it's easy to get invalid Saturation values way above 1.0, indicating the color can't be represented in HPLuv because it's not pastel.
+- **Oklab:** A perceptual color space by Björn Ottosson that improves on CIE-L\*a\*b\* with better perceptual uniformity, especially for blue hues. L in [0..1], a and b roughly in [-0.5..0.5]. See [Oklab](https://bottosson.github.io/posts/oklab/).
+- **Oklch:** The cylindrical (polar) representation of Oklab, similar to HCL. L in [0..1], C roughly in [0..0.5], h° in [0..360].
For the colorspaces where it makes sense (XYZ, Lab, Luv, HCl), the
[D65](http://en.wikipedia.org/wiki/Illuminant_D65) is used as reference white
@@ -52,14 +55,6 @@ Nice, but what's it useful for?
- Generating random colors under some constraints (e.g. colors of the same shade, or shades of one color.)
- Generating gorgeous random palettes with distinct colors of a same temperature.
-What not (yet)?
-===============
-There are a few features which are currently missing and might be useful.
-I just haven't implemented them yet because I didn't have the need for it.
-Pull requests welcome.
-
-- Sorting colors (potentially using above mentioned distances)
-
So which colorspace should I use?
=================================
It depends on what you want to do. I think the folks from *I want hue* are
@@ -103,6 +98,8 @@ c = colorful.Xyy(0.219895, 0.221839, 0.190837)
c = colorful.Lab(0.507850, 0.040585,-0.370945)
c = colorful.Luv(0.507849,-0.194172,-0.567924)
c = colorful.Hcl(276.2440, 0.373160, 0.507849)
+c = colorful.OkLab(0.577227, -0.021391, -0.104541)
+c = colorful.OkLch(0.577227, 0.106707, 258.435657)
fmt.Printf("RGB values: %v, %v, %v", c.R, c.G, c.B)
```
@@ -116,6 +113,8 @@ x, y, Y := c.Xyy()
l, a, b := c.Lab()
l, u, v := c.Luv()
h, c, l := c.Hcl()
+l, a, b = c.OkLab()
+l, c, h = c.OkLch()
```
Note that, because of Go's unfortunate choice of requiring an initial uppercase,
@@ -139,7 +138,7 @@ alpha colors, this means the RGB values are lost (set to 0) and it's impossible
to recover them. In such a case `MakeColor` will return `false` as its second value.
### Comparing colors
-In the RGB color space, the Euclidian distance between colors *doesn't* correspond
+In the RGB color space, the Euclidean distance between colors *doesn't* correspond
to visual/perceptual distance. This means that two pairs of colors which have the
same distance in RGB space can look much further apart. This is fixed by the
CIE-L\*a\*b\*, CIE-L\*u\*v\* and CIE-L\*C\*h° color spaces.
@@ -197,7 +196,7 @@ it only if you really know what you're doing. It will eat your cat.
Blending is highly connected to distance, since it basically "walks through" the
colorspace thus, if the colorspace maps distances well, the walk is "smooth".
-Colorful comes with blending functions in RGB, HSV and any of the LAB spaces.
+Colorful comes with blending functions in RGB, HSV, Oklab, Oklch, and any of the CIE-LAB spaces.
Of course, you'd rather want to use the blending functions of the LAB spaces since
these spaces map distances well but, just in case, here is an example showing
you how the blendings (`#fdffcc` to `#242a42`) are done in the various spaces:
@@ -208,7 +207,7 @@ What you see is that HSV is really bad: it adds some green, which is not present
in the original colors at all! RGB is much better, but it stays light a little
too long. LUV and LAB both hit the right lightness but LAB has a little more
color. HCL works in the same vein as HSV (both cylindrical interpolations) but
-it does it right in that there is no green appearing and the lighthness changes
+it does it right in that there is no green appearing and the lightness changes
in a linear manner.
While this seems all good, you need to know one thing: When interpolating in any
@@ -316,11 +315,11 @@ generating this picture in `doc/colorgens/colorgens.go`.
### Getting random palettes
As soon as you need to generate more than one random color, you probably want
-them to be distinguishible. Playing against an opponent which has almost the
+them to be distinguishable. Playing against an opponent which has almost the
same blue as I do is not fun. This is where random palettes can help.
These palettes are generated using an algorithm which ensures that all colors
-on the palette are as distinguishible as possible. Again, there is a `Fast`
+on the palette are as distinguishable as possible. Again, there is a `Fast`
method which works in HSV and is less perceptually uniform and a non-`Fast`
method which works in CIE spaces. For more theory on `SoftPalette`, check out
[I want hue](http://tools.medialab.sciences-po.fr/iwanthue/theory.php). Yet
@@ -372,10 +371,18 @@ from top to bottom: `Warm`, `FastWarm`, `Happy`, `FastHappy`, `Soft`,
Again, the code used for generating the above image is available as [doc/palettegens/palettegens.go](https://github.com/lucasb-eyer/go-colorful/blob/master/doc/palettegens/palettegens.go).
### Sorting colors
-TODO: Sort using dist fn.
+
+Sorting colors is not a well-defined operation. For example, {dark blue, dark red, light blue, light red} is already sorted if darker colors should precede lighter colors but would need to be re-sorted as {dark red, light red, dark blue, light blue} if longer-wavelength colors should precede shorter-wavelength colors.
+
+Go-Colorful's `Sorted` function orders a list of colors so as to minimize the average distance between adjacent colors, including between the last and the first. (`Sorted` does not necessarily find the true minimum, only a reasonably close approximation.) The following picture, drawn by [doc/colorsort/colorsort.go](https://github.com/lucasb-eyer/go-colorful/blob/master/doc/colorsort/colorsort.go), illustrates `Sorted`'s behavior:
+
+
+
+The first row represents the input: a slice of 512 randomly chosen colors. The second row shows the colors sorted in CIE-L\*C\*h° space, ordered first by lightness (L), then by hue angle (h), and finally by chroma (C). Note that distracting pinstripes permeate the colors. Sorting using *any* color space and *any* ordering of the channels yields a similar pinstriped pattern. The third row of the image was sorted using Go-Colorful's `Sorted` function. Although the colors do not appear to be in any particular order, the sequence at least appears smoother than the one sorted by channel.
+
### Using linear RGB for computations
-There are two methods for transforming RGB<->Linear RGB: a fast and almost precise one,
+There are two methods for transforming RGB⟷Linear RGB: a fast and almost precise one,
and a slow and precise one.
```go
@@ -471,11 +478,12 @@ section above.
Who?
====
-This library was developed by Lucas Beyer with contributions from
-Bastien Dejean (@baskerville), Phil Kulak (@pkulak) and Christian Muehlhaeuser (@muesli).
-
-It is now maintained by makeworld (@makeworld-the-better-one).
+This library was originally developed by Lucas Beyer, with notable
+contributions from Bastien Dejean (@baskerville), Phil Kulak (@pkulak),
+Christian Muehlhaeuser (@muesli), Scott Pakin (@spakin), and many others.
+See the [contributors list](https://github.com/lucasb-eyer/go-colorful/graphs/contributors) for the full roster.
+It is currently maintained by makeworld (@makew0rld).
## License
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go b/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go
index 2e2e49e1..ac697d65 100644
--- a/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go
+++ b/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go
@@ -2,28 +2,32 @@
package colorful
-import (
- "math/rand"
-)
-
// Creates a random dark, "warm" color through a restricted HSV space.
-func FastWarmColor() Color {
+func FastWarmColorWithRand(rand RandInterface) Color {
return Hsv(
rand.Float64()*360.0,
0.5+rand.Float64()*0.3,
0.3+rand.Float64()*0.3)
}
+func FastWarmColor() Color {
+ return FastWarmColorWithRand(getDefaultGlobalRand())
+}
+
// Creates a random dark, "warm" color through restricted HCL space.
// This is slower than FastWarmColor but will likely give you colors which have
// the same "warmness" if you run it many times.
-func WarmColor() (c Color) {
- for c = randomWarm(); !c.IsValid(); c = randomWarm() {
+func WarmColorWithRand(rand RandInterface) (c Color) {
+ for c = randomWarmWithRand(rand); !c.IsValid(); c = randomWarmWithRand(rand) {
}
return
}
-func randomWarm() Color {
+func WarmColor() (c Color) {
+ return WarmColorWithRand(getDefaultGlobalRand())
+}
+
+func randomWarmWithRand(rand RandInterface) Color {
return Hcl(
rand.Float64()*360.0,
0.1+rand.Float64()*0.3,
@@ -31,23 +35,31 @@ func randomWarm() Color {
}
// Creates a random bright, "pimpy" color through a restricted HSV space.
-func FastHappyColor() Color {
+func FastHappyColorWithRand(rand RandInterface) Color {
return Hsv(
rand.Float64()*360.0,
0.7+rand.Float64()*0.3,
0.6+rand.Float64()*0.3)
}
+func FastHappyColor() Color {
+ return FastHappyColorWithRand(getDefaultGlobalRand())
+}
+
// Creates a random bright, "pimpy" color through restricted HCL space.
// This is slower than FastHappyColor but will likely give you colors which
// have the same "brightness" if you run it many times.
-func HappyColor() (c Color) {
- for c = randomPimp(); !c.IsValid(); c = randomPimp() {
+func HappyColorWithRand(rand RandInterface) (c Color) {
+ for c = randomPimpWithRand(rand); !c.IsValid(); c = randomPimpWithRand(rand) {
}
return
}
-func randomPimp() Color {
+func HappyColor() (c Color) {
+ return HappyColorWithRand(getDefaultGlobalRand())
+}
+
+func randomPimpWithRand(rand RandInterface) Color {
return Hcl(
rand.Float64()*360.0,
0.5+rand.Float64()*0.3,
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/colors.go b/vendor/github.com/lucasb-eyer/go-colorful/colors.go
index 0d5bffe5..17441a8c 100644
--- a/vendor/github.com/lucasb-eyer/go-colorful/colors.go
+++ b/vendor/github.com/lucasb-eyer/go-colorful/colors.go
@@ -5,6 +5,7 @@ import (
"fmt"
"image/color"
"math"
+ "strconv"
)
// A color is stored internally using sRGB (standard RGB) values in the range 0-1
@@ -94,15 +95,39 @@ func (c1 Color) DistanceRgb(c2 Color) float64 {
return math.Sqrt(sq(c1.R-c2.R) + sq(c1.G-c2.G) + sq(c1.B-c2.B))
}
-// DistanceLinearRGB computes the distance between two colors in linear RGB
+// DistanceLinearRgb computes the distance between two colors in linear RGB
// space. This is not useful for measuring how humans perceive color, but
// might be useful for other things, like dithering.
-func (c1 Color) DistanceLinearRGB(c2 Color) float64 {
+func (c1 Color) DistanceLinearRgb(c2 Color) float64 {
r1, g1, b1 := c1.LinearRgb()
r2, g2, b2 := c2.LinearRgb()
return math.Sqrt(sq(r1-r2) + sq(g1-g2) + sq(b1-b2))
}
+// DistanceLinearRGB is deprecated in favour of DistanceLinearRgb.
+// They do the exact same thing.
+func (c1 Color) DistanceLinearRGB(c2 Color) float64 {
+ return c1.DistanceLinearRgb(c2)
+}
+
+// DistanceRiemersma is a color distance algorithm developed by Thiadmer Riemersma.
+// It uses RGB coordinates, but he claims it has similar results to CIELUV.
+// This makes it both fast and accurate.
+//
+// Sources:
+//
+// https://www.compuphase.com/cmetric.htm
+// https://github.com/lucasb-eyer/go-colorful/issues/52
+func (c1 Color) DistanceRiemersma(c2 Color) float64 {
+ rAvg := (c1.R + c2.R) / 2.0
+ // Deltas
+ dR := c1.R - c2.R
+ dG := c1.G - c2.G
+ dB := c1.B - c2.B
+
+ return math.Sqrt((2+rAvg)*dR*dR + 4*dG*dG + (2+(1-rAvg))*dB*dB)
+}
+
// Check for equality between colors within the tolerance Delta (1/255).
func (c1 Color) AlmostEqualRgb(c2 Color) bool {
return math.Abs(c1.R-c2.R)+
@@ -112,9 +137,11 @@ func (c1 Color) AlmostEqualRgb(c2 Color) bool {
// You don't really want to use this, do you? Go for BlendLab, BlendLuv or BlendHcl.
func (c1 Color) BlendRgb(c2 Color, t float64) Color {
- return Color{c1.R + t*(c2.R-c1.R),
+ return Color{
+ c1.R + t*(c2.R-c1.R),
c1.G + t*(c2.G-c1.G),
- c1.B + t*(c2.B-c1.B)}
+ c1.B + t*(c2.B-c1.B),
+ }
}
// Utility used by Hxx color-spaces for interpolating between two angles in [0,360].
@@ -128,9 +155,9 @@ func interp_angle(a0, a1, t float64) float64 {
/// HSV ///
///////////
// From http://en.wikipedia.org/wiki/HSL_and_HSV
-// Note that h is in [0..360] and s,v in [0..1]
+// Note that h is in [0..359] and s,v in [0..1]
-// Hsv returns the Hue [0..360], Saturation and Value [0..1] of the color.
+// Hsv returns the Hue [0..359], Saturation and Value [0..1] of the color.
func (col Color) Hsv() (h, s, v float64) {
min := math.Min(math.Min(col.R, col.G), col.B)
v = math.Max(math.Max(col.R, col.G), col.B)
@@ -160,7 +187,7 @@ func (col Color) Hsv() (h, s, v float64) {
return
}
-// Hsv creates a new Color given a Hue in [0..360], a Saturation and a Value in [0..1]
+// Hsv creates a new Color given a Hue in [0..359], a Saturation and a Value in [0..1]
func Hsv(H, S, V float64) Color {
Hp := H / 60.0
C := V * S
@@ -198,6 +225,13 @@ func (c1 Color) BlendHsv(c2 Color, t float64) Color {
h1, s1, v1 := c1.Hsv()
h2, s2, v2 := c2.Hsv()
+ // https://github.com/lucasb-eyer/go-colorful/pull/60
+ if s1 == 0 && s2 != 0 {
+ h1 = h2
+ } else if s2 == 0 && s1 != 0 {
+ h2 = h1
+ }
+
// We know that h are both in [0..360]
return Hsv(interp_angle(h1, h2, t), s1+t*(s2-s1), v1+t*(v2-v1))
}
@@ -205,7 +239,7 @@ func (c1 Color) BlendHsv(c2 Color, t float64) Color {
/// HSL ///
///////////
-// Hsl returns the Hue [0..360], Saturation [0..1], and Luminance (lightness) [0..1] of the color.
+// Hsl returns the Hue [0..359], Saturation [0..1], and Luminance (lightness) [0..1] of the color.
func (col Color) Hsl() (h, s, l float64) {
min := math.Min(math.Min(col.R, col.G), col.B)
max := math.Max(math.Max(col.R, col.G), col.B)
@@ -240,7 +274,7 @@ func (col Color) Hsl() (h, s, l float64) {
return
}
-// Hsl creates a new Color given a Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1]
+// Hsl creates a new Color given a Hue in [0..359], a Saturation [0..1], and a Luminance (lightness) in [0..1]
func Hsl(h, s, l float64) Color {
if s == 0 {
return Color{l, l, l}
@@ -331,23 +365,46 @@ func (col Color) Hex() string {
// Hex parses a "html" hex color-string, either in the 3 "#f0c" or 6 "#ff1034" digits form.
func Hex(scol string) (Color, error) {
- format := "#%02x%02x%02x"
- factor := 1.0 / 255.0
- if len(scol) == 4 {
- format = "#%1x%1x%1x"
- factor = 1.0 / 15.0
+ if scol == "" || scol[0] != '#' {
+ return Color{}, fmt.Errorf("color: %v is not a hex-color", scol)
+ }
+ var c Color
+ var err error
+ switch len(scol) {
+ case 4:
+ c, err = parseHexColor(scol[1:2], scol[2:3], scol[3:4], 4, 1.0/15.0)
+ case 7:
+ c, err = parseHexColor(scol[1:3], scol[3:5], scol[5:7], 8, 1.0/255.0)
+ default:
+ return Color{}, fmt.Errorf("color: %v is not a hex-color", scol)
}
-
- var r, g, b uint8
- n, err := fmt.Sscanf(scol, format, &r, &g, &b)
if err != nil {
+ return Color{}, fmt.Errorf("color: %v is not a hex-color: %w", scol, err)
+ }
+ return c, nil
+}
+
+func parseHexColor(r, g, b string, bits int, factor float64) (Color, error) {
+ var c Color
+ var v uint64
+ var err error
+
+ if v, err = strconv.ParseUint(r, 16, bits); err != nil {
return Color{}, err
}
- if n != 3 {
- return Color{}, fmt.Errorf("color: %v is not a hex-color", scol)
+ c.R = float64(v) * factor
+
+ if v, err = strconv.ParseUint(g, 16, bits); err != nil {
+ return Color{}, err
}
+ c.G = float64(v) * factor
- return Color{float64(r) * factor, float64(g) * factor, float64(b) * factor}, nil
+ if v, err = strconv.ParseUint(b, 16, bits); err != nil {
+ return Color{}, err
+ }
+ c.B = float64(v) * factor
+
+ return c, err
}
/// Linear ///
@@ -377,7 +434,7 @@ func linearize_fast(v float64) float64 {
v2 := v1 * v1
v3 := v2 * v1
v4 := v2 * v2
- //v5 := v3*v2
+ // v5 := v3*v2
return -0.248750514614486 + 0.925583310193438*v + 1.16740237321695*v2 + 0.280457026598666*v3 - 0.0757991963780179*v4 //+ 0.0437040411548932*v5
}
@@ -450,6 +507,19 @@ func LinearRgbToXyz(r, g, b float64) (x, y, z float64) {
return
}
+// BlendLinearRgb blends two colors in the Linear RGB color-space.
+// Unlike BlendRgb, this will not produce dark color around the center.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendLinearRgb(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.LinearRgb()
+ r2, g2, b2 := c2.LinearRgb()
+ return LinearRgb(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1),
+ )
+}
+
/// XYZ ///
///////////
// http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/
@@ -784,7 +854,7 @@ func LuvToXyz(l, u, v float64) (x, y, z float64) {
}
func LuvToXyzWhiteRef(l, u, v float64, wref [3]float64) (x, y, z float64) {
- //y = wref[1] * lab_finv((l + 0.16) / 1.16)
+ // y = wref[1] * lab_finv((l + 0.16) / 1.16)
if l <= 0.08 {
y = wref[1] * l * 100.0 * 3.0 / 29.0 * 3.0 / 29.0 * 3.0 / 29.0
} else {
@@ -913,6 +983,13 @@ func (col1 Color) BlendHcl(col2 Color, t float64) Color {
h1, c1, l1 := col1.Hcl()
h2, c2, l2 := col2.Hcl()
+ // https://github.com/lucasb-eyer/go-colorful/pull/60
+ if c1 <= 0.00015 && c2 >= 0.00015 {
+ h1 = h2
+ } else if c2 <= 0.00015 && c1 >= 0.00015 {
+ h2 = h1
+ }
+
// We know that h are both in [0..360]
return Hcl(interp_angle(h1, h2, t), c1+t*(c2-c1), l1+t*(l2-l1)).Clamped()
}
@@ -977,3 +1054,103 @@ func (col1 Color) BlendLuvLCh(col2 Color, t float64) Color {
// We know that h are both in [0..360]
return LuvLCh(l1+t*(l2-l1), c1+t*(c2-c1), interp_angle(h1, h2, t))
}
+
+/// OkLab ///
+///////////
+
+func (col Color) OkLab() (l, a, b float64) {
+ return XyzToOkLab(col.Xyz())
+}
+
+func OkLab(l, a, b float64) Color {
+ return Xyz(OkLabToXyz(l, a, b))
+}
+
+func XyzToOkLab(x, y, z float64) (l, a, b float64) {
+ l_ := math.Cbrt(0.8189330101*x + 0.3618667424*y - 0.1288597137*z)
+ m_ := math.Cbrt(0.0329845436*x + 0.9293118715*y + 0.0361456387*z)
+ s_ := math.Cbrt(0.0482003018*x + 0.2643662691*y + 0.6338517070*z)
+ l = 0.2104542553*l_ + 0.7936177850*m_ - 0.0040720468*s_
+ a = 1.9779984951*l_ - 2.4285922050*m_ + 0.4505937099*s_
+ b = 0.0259040371*l_ + 0.7827717662*m_ - 0.8086757660*s_
+ return
+}
+
+func OkLabToXyz(l, a, b float64) (x, y, z float64) {
+ l_ := 0.9999999984505196*l + 0.39633779217376774*a + 0.2158037580607588*b
+ m_ := 1.0000000088817607*l - 0.10556134232365633*a - 0.0638541747717059*b
+ s_ := 1.0000000546724108*l - 0.08948418209496574*a - 1.2914855378640917*b
+
+ ll := math.Pow(l_, 3)
+ m := math.Pow(m_, 3)
+ s := math.Pow(s_, 3)
+
+ x = 1.2268798733741557*ll - 0.5578149965554813*m + 0.28139105017721594*s
+ y = -0.04057576262431372*ll + 1.1122868293970594*m - 0.07171106666151696*s
+ z = -0.07637294974672142*ll - 0.4214933239627916*m + 1.5869240244272422*s
+
+ return
+}
+
+// BlendOkLab blends two colors in the OkLab color-space, which should result in a better blend (even compared to BlendLab).
+func (c1 Color) BlendOkLab(c2 Color, t float64) Color {
+ l1, a1, b1 := c1.OkLab()
+ l2, a2, b2 := c2.OkLab()
+ return OkLab(l1+t*(l2-l1),
+ a1+t*(a2-a1),
+ b1+t*(b2-b1))
+}
+
+/// OkLch ///
+///////////
+
+func (col Color) OkLch() (l, c, h float64) {
+ return OkLabToOkLch(col.OkLab())
+}
+
+func OkLch(l, c, h float64) Color {
+ return Xyz(OkLchToXyz(l, c, h))
+}
+
+func XyzToOkLch(x, y, z float64) (float64, float64, float64) {
+ l, c, h := OkLabToOkLch(XyzToOkLab(x, y, z))
+ return l, c, h
+}
+
+func OkLchToXyz(l, c, h float64) (float64, float64, float64) {
+ x, y, z := OkLabToXyz(OkLchToOkLab(l, c, h))
+ return x, y, z
+}
+
+func OkLabToOkLch(l, a, b float64) (float64, float64, float64) {
+ c := math.Sqrt((a * a) + (b * b))
+ h := math.Atan2(b, a)
+ if h < 0 {
+ h += 2 * math.Pi
+ }
+
+ return l, c, h * 180 / math.Pi
+}
+
+func OkLchToOkLab(l, c, h float64) (float64, float64, float64) {
+ h *= math.Pi / 180
+ a := c * math.Cos(h)
+ b := c * math.Sin(h)
+ return l, a, b
+}
+
+// BlendOkLch blends two colors in the OkLch color-space, which should result in a better blend (even compared to BlendHcl).
+func (col1 Color) BlendOkLch(col2 Color, t float64) Color {
+ l1, c1, h1 := col1.OkLch()
+ l2, c2, h2 := col2.OkLch()
+
+ // https://github.com/lucasb-eyer/go-colorful/pull/60
+ if c1 <= 0.00015 && c2 >= 0.00015 {
+ h1 = h2
+ } else if c2 <= 0.00015 && c1 >= 0.00015 {
+ h2 = h1
+ }
+
+ // We know that h are both in [0..360]
+ return OkLch(l1+t*(l2-l1), c1+t*(c2-c1), interp_angle(h1, h2, t)).Clamped()
+}
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go b/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go
index bb66dfa4..0cb9286c 100644
--- a/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go
+++ b/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go
@@ -1,13 +1,9 @@
package colorful
-import (
- "math/rand"
-)
-
// Uses the HSV color space to generate colors with similar S,V but distributed
// evenly along their Hue. This is fast but not always pretty.
// If you've got time to spare, use Lab (the non-fast below).
-func FastHappyPalette(colorsCount int) (colors []Color) {
+func FastHappyPaletteWithRand(colorsCount int, rand RandInterface) (colors []Color) {
colors = make([]Color, colorsCount)
for i := 0; i < colorsCount; i++ {
@@ -16,10 +12,18 @@ func FastHappyPalette(colorsCount int) (colors []Color) {
return
}
-func HappyPalette(colorsCount int) ([]Color, error) {
+func FastHappyPalette(colorsCount int) (colors []Color) {
+ return FastHappyPaletteWithRand(colorsCount, getDefaultGlobalRand())
+}
+
+func HappyPaletteWithRand(colorsCount int, rand RandInterface) ([]Color, error) {
pimpy := func(l, a, b float64) bool {
_, c, _ := LabToHcl(l, a, b)
return 0.3 <= c && 0.4 <= l && l <= 0.8
}
- return SoftPaletteEx(colorsCount, SoftPaletteSettings{pimpy, 50, true})
+ return SoftPaletteExWithRand(colorsCount, SoftPaletteSettings{pimpy, 50, true}, rand)
+}
+
+func HappyPalette(colorsCount int) ([]Color, error) {
+ return HappyPaletteWithRand(colorsCount, getDefaultGlobalRand())
}
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go b/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go
index 76f31d8f..26f35730 100644
--- a/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go
+++ b/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go
@@ -34,6 +34,10 @@ func (hc *HexColor) Value() (driver.Value, error) {
return Color(*hc).Hex(), nil
}
+func (hc HexColor) String() string {
+ return Color(hc).Hex()
+}
+
func (e errUnsupportedType) Error() string {
return fmt.Sprintf("unsupported type: got %v, want a %s", e.got, e.want)
}
@@ -65,3 +69,23 @@ func (hc *HexColor) Decode(hexCode string) error {
*hc = HexColor(col)
return nil
}
+
+func (hc HexColor) MarshalYAML() (interface{}, error) {
+ return Color(hc).Hex(), nil
+}
+
+func (hc *HexColor) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var hexCode string
+ if err := unmarshal(&hexCode); err != nil {
+ return err
+ }
+
+ var col, err = Hex(hexCode)
+ if err != nil {
+ return err
+ }
+
+ *hc = HexColor(col)
+
+ return nil
+}
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go b/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go
index d19fb644..cc514882 100644
--- a/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go
+++ b/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go
@@ -11,7 +11,8 @@ import "math"
// comparing to the test values, this modified white reference is used internally.
//
// See this GitHub thread for details on these values:
-// https://github.com/hsluv/hsluv/issues/79
+//
+// https://github.com/hsluv/hsluv/issues/79
var hSLuvD65 = [3]float64{0.95045592705167, 1.0, 1.089057750759878}
func LuvLChToHSLuv(l, c, h float64) (float64, float64, float64) {
@@ -115,7 +116,7 @@ func (col Color) HPLuv() (h, s, l float64) {
return LuvLChToHPLuv(col.LuvLChWhiteRef(hSLuvD65))
}
-// DistanceHSLuv calculates Euclidan distance in the HSLuv colorspace. No idea
+// DistanceHSLuv calculates Euclidean distance in the HSLuv colorspace. No idea
// how useful this is.
//
// The Hue value is divided by 100 before the calculation, so that H, S, and L
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/rand.go b/vendor/github.com/lucasb-eyer/go-colorful/rand.go
new file mode 100644
index 00000000..d3a2d5b5
--- /dev/null
+++ b/vendor/github.com/lucasb-eyer/go-colorful/rand.go
@@ -0,0 +1,22 @@
+package colorful
+
+import "math/rand"
+
+type RandInterface interface {
+ Float64() float64
+ Intn(n int) int
+}
+
+type defaultGlobalRand struct{}
+
+func (df defaultGlobalRand) Float64() float64 {
+ return rand.Float64()
+}
+
+func (df defaultGlobalRand) Intn(n int) int {
+ return rand.Intn(n)
+}
+
+func getDefaultGlobalRand() RandInterface {
+ return defaultGlobalRand{}
+}
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go b/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go
index 9f7bf6f7..6d8aa137 100644
--- a/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go
+++ b/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go
@@ -6,7 +6,6 @@ package colorful
import (
"fmt"
"math"
- "math/rand"
)
// The algorithm works in L*a*b* color space and converts to RGB in the end.
@@ -32,7 +31,7 @@ type SoftPaletteSettings struct {
// as a new palette of distinctive colors. Falls back to K-medoid if the mean
// happens to fall outside of the color-space, which can only happen if you
// specify a CheckColor function.
-func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, error) {
+func SoftPaletteExWithRand(colorsCount int, settings SoftPaletteSettings, rand RandInterface) ([]Color, error) {
// Checks whether it's a valid RGB and also fulfills the potentially provided constraint.
check := func(col lab_t) bool {
@@ -79,7 +78,7 @@ func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, erro
// The actual k-means/medoid iterations
for i := 0; i < settings.Iterations; i++ {
- // Reassing the samples to clusters, i.e. to their closest mean.
+ // Reassigning the samples to clusters, i.e. to their closest mean.
// By the way, also check if any sample is used as a medoid and if so, mark that.
for isample, sample := range samples {
samples_used[isample] = false
@@ -100,7 +99,7 @@ func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, erro
// Compute new means according to the samples.
for imean := range means {
- // The new mean is the average of all samples belonging to it..
+ // The new mean is the average of all samples belonging to it.
nsamples := 0
newmean := lab_t{0.0, 0.0, 0.0}
for isample, sample := range samples {
@@ -148,9 +147,17 @@ func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, erro
return labs2cols(means), nil
}
+func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, error) {
+ return SoftPaletteExWithRand(colorsCount, settings, getDefaultGlobalRand())
+}
+
// A wrapper which uses common parameters.
+func SoftPaletteWithRand(colorsCount int, rand RandInterface) ([]Color, error) {
+ return SoftPaletteExWithRand(colorsCount, SoftPaletteSettings{nil, 50, false}, rand)
+}
+
func SoftPalette(colorsCount int) ([]Color, error) {
- return SoftPaletteEx(colorsCount, SoftPaletteSettings{nil, 50, false})
+ return SoftPaletteWithRand(colorsCount, getDefaultGlobalRand())
}
func in(haystack []lab_t, upto int, needle lab_t) bool {
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/sort.go b/vendor/github.com/lucasb-eyer/go-colorful/sort.go
new file mode 100644
index 00000000..b1c1b681
--- /dev/null
+++ b/vendor/github.com/lucasb-eyer/go-colorful/sort.go
@@ -0,0 +1,191 @@
+// This file provides functions for sorting colors.
+
+package colorful
+
+import (
+ "math"
+ "sort"
+)
+
+// An element represents a single element of a set. It is used to
+// implement a disjoint-set forest.
+type element struct {
+ parent *element // Parent element
+ rank int // Rank (approximate depth) of the subtree with this element as root
+}
+
+// newElement creates a singleton set and returns its sole element.
+func newElement() *element {
+ s := &element{}
+ s.parent = s
+ return s
+}
+
+// find returns an arbitrary element of a set when invoked on any element of
+// the set, The important feature is that it returns the same value when
+// invoked on any element of the set. Consequently, it can be used to test if
+// two elements belong to the same set.
+func (e *element) find() *element {
+ for e.parent != e {
+ e.parent = e.parent.parent
+ e = e.parent
+ }
+ return e
+}
+
+// union establishes the union of two sets when given an element from each set.
+// Afterwards, the original sets no longer exist as separate entities.
+func union(e1, e2 *element) {
+ // Ensure the two elements aren't already part of the same union.
+ e1Root := e1.find()
+ e2Root := e2.find()
+ if e1Root == e2Root {
+ return
+ }
+
+ // Create a union by making the shorter tree point to the root of the
+ // larger tree.
+ switch {
+ case e1Root.rank < e2Root.rank:
+ e1Root.parent = e2Root
+ case e1Root.rank > e2Root.rank:
+ e2Root.parent = e1Root
+ default:
+ e2Root.parent = e1Root
+ e1Root.rank++
+ }
+}
+
+// An edgeIdxs describes an edge in a graph or tree. The vertices in the edge
+// are indexes into a list of Color values.
+type edgeIdxs [2]int
+
+// An edgeDistance is a map from an edge (pair of indices) to a distance
+// between the two vertices.
+type edgeDistance map[edgeIdxs]float64
+
+// allToAllDistancesCIEDE2000 computes the CIEDE2000 distance between each pair of
+// colors. It returns a map from a pair of indices (u, v) with u < v to a
+// distance.
+func allToAllDistancesCIEDE2000(cs []Color) edgeDistance {
+ nc := len(cs)
+ m := make(edgeDistance, nc*nc)
+ for u := 0; u < nc-1; u++ {
+ for v := u + 1; v < nc; v++ {
+ m[edgeIdxs{u, v}] = cs[u].DistanceCIEDE2000(cs[v])
+ }
+ }
+ return m
+}
+
+// sortEdges sorts all edges in a distance map by increasing vertex distance.
+func sortEdges(m edgeDistance) []edgeIdxs {
+ es := make([]edgeIdxs, 0, len(m))
+ for uv := range m {
+ es = append(es, uv)
+ }
+ sort.Slice(es, func(i, j int) bool {
+ return m[es[i]] < m[es[j]]
+ })
+ return es
+}
+
+// minSpanTree computes a minimum spanning tree from a vertex count and a
+// distance-sorted edge list. It returns the subset of edges that belong to
+// the tree, including both (u, v) and (v, u) for each edge.
+func minSpanTree(nc int, es []edgeIdxs) map[edgeIdxs]struct{} {
+ // Start with each vertex in its own set.
+ elts := make([]*element, nc)
+ for i := range elts {
+ elts[i] = newElement()
+ }
+
+ // Run Kruskal's algorithm to construct a minimal spanning tree.
+ mst := make(map[edgeIdxs]struct{}, nc)
+ for _, uv := range es {
+ u, v := uv[0], uv[1]
+ if elts[u].find() == elts[v].find() {
+ continue // Same set: edge would introduce a cycle.
+ }
+ mst[uv] = struct{}{}
+ mst[edgeIdxs{v, u}] = struct{}{}
+ union(elts[u], elts[v])
+ }
+ return mst
+}
+
+// traverseMST walks a minimum spanning tree in prefix order.
+func traverseMST(mst map[edgeIdxs]struct{}, root int) []int {
+ // Compute a list of neighbors for each vertex.
+ neighs := make(map[int][]int, len(mst))
+ for uv := range mst {
+ u, v := uv[0], uv[1]
+ neighs[u] = append(neighs[u], v)
+ }
+ for u, vs := range neighs {
+ sort.Ints(vs)
+ copy(neighs[u], vs)
+ }
+
+ // Walk the tree from a given vertex.
+ order := make([]int, 0, len(neighs))
+ visited := make(map[int]bool, len(neighs))
+ var walkFrom func(int)
+ walkFrom = func(r int) {
+ // Visit the starting vertex.
+ order = append(order, r)
+ visited[r] = true
+
+ // Recursively visit each child in turn.
+ for _, c := range neighs[r] {
+ if !visited[c] {
+ walkFrom(c)
+ }
+ }
+ }
+ walkFrom(root)
+ return order
+}
+
+// Sorted sorts a list of Color values. Sorting is not a well-defined operation
+// for colors so the intention here primarily is to order colors so that the
+// transition from one to the next is fairly smooth.
+func Sorted(cs []Color) []Color {
+ // Do nothing in trivial cases.
+ newCs := make([]Color, len(cs))
+ if len(cs) < 2 {
+ copy(newCs, cs)
+ return newCs
+ }
+
+ // Compute the distance from each color to every other color.
+ dists := allToAllDistancesCIEDE2000(cs)
+
+ // Produce a list of edges in increasing order of the distance between
+ // their vertices.
+ edges := sortEdges(dists)
+
+ // Construct a minimum spanning tree from the list of edges.
+ mst := minSpanTree(len(cs), edges)
+
+ // Find the darkest color in the list.
+ var black Color
+ var dIdx int // Index of darkest color
+ light := math.MaxFloat64 // Lightness of darkest color (distance from black)
+ for i, c := range cs {
+ d := black.DistanceCIEDE2000(c)
+ if d < light {
+ dIdx = i
+ light = d
+ }
+ }
+
+ // Traverse the tree starting from the darkest color.
+ idxs := traverseMST(mst, dIdx)
+
+ // Convert the index list to a list of colors, overwriting the input.
+ for i, idx := range idxs {
+ newCs[i] = cs[idx]
+ }
+ return newCs
+}
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go b/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go
index 00f42a5c..d294fb41 100644
--- a/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go
+++ b/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go
@@ -1,13 +1,9 @@
package colorful
-import (
- "math/rand"
-)
-
// Uses the HSV color space to generate colors with similar S,V but distributed
// evenly along their Hue. This is fast but not always pretty.
// If you've got time to spare, use Lab (the non-fast below).
-func FastWarmPalette(colorsCount int) (colors []Color) {
+func FastWarmPaletteWithRand(colorsCount int, rand RandInterface) (colors []Color) {
colors = make([]Color, colorsCount)
for i := 0; i < colorsCount; i++ {
@@ -16,10 +12,18 @@ func FastWarmPalette(colorsCount int) (colors []Color) {
return
}
-func WarmPalette(colorsCount int) ([]Color, error) {
+func FastWarmPalette(colorsCount int) (colors []Color) {
+ return FastWarmPaletteWithRand(colorsCount, getDefaultGlobalRand())
+}
+
+func WarmPaletteWithRand(colorsCount int, rand RandInterface) ([]Color, error) {
warmy := func(l, a, b float64) bool {
_, c, _ := LabToHcl(l, a, b)
return 0.1 <= c && c <= 0.4 && 0.2 <= l && l <= 0.5
}
- return SoftPaletteEx(colorsCount, SoftPaletteSettings{warmy, 50, true})
+ return SoftPaletteExWithRand(colorsCount, SoftPaletteSettings{warmy, 50, true}, rand)
+}
+
+func WarmPalette(colorsCount int) ([]Color, error) {
+ return WarmPaletteWithRand(colorsCount, getDefaultGlobalRand())
}
diff --git a/vendor/github.com/lucasb-eyer/go-colorful/widegamut.go b/vendor/github.com/lucasb-eyer/go-colorful/widegamut.go
new file mode 100644
index 00000000..63c3e878
--- /dev/null
+++ b/vendor/github.com/lucasb-eyer/go-colorful/widegamut.go
@@ -0,0 +1,290 @@
+package colorful
+
+import "math"
+
+// Wide-gamut RGB color spaces from CSS Color Level 4.
+// https://www.w3.org/TR/css-color-4/#color-conversion-code
+
+/// Bradford ///
+////////////////
+// Bradford chromatic adaptation between D50 and D65 illuminants.
+
+func D50ToD65(x, y, z float64) (xo, yo, zo float64) {
+ xo = 0.9554734527042182*x - 0.023098536874261423*y + 0.06325964552894382*z
+ yo = -0.028369706963208136*x + 1.0099954580058226*y + 0.021041398966943008*z
+ zo = 0.012314001688319899*x - 0.020507696433477912*y + 1.3303659366080753*z
+ return
+}
+
+func D65ToD50(x, y, z float64) (xo, yo, zo float64) {
+ xo = 1.0479298208405488*x + 0.022946793341019088*y - 0.05019222954313557*z
+ yo = 0.029627815688159344*x + 0.990434484573249*y - 0.01707382502938514*z
+ zo = -0.009243058152591178*x + 0.015055144896577895*y + 0.7518742899580008*z
+ return
+}
+
+/// XYZ D50 ///
+///////////////
+
+func XyzD50(x, y, z float64) Color {
+ return Xyz(D50ToD65(x, y, z))
+}
+
+func (col Color) XyzD50() (x, y, z float64) {
+ return D65ToD50(col.Xyz())
+}
+
+/// Display P3 ///
+//////////////////
+// Uses the sRGB transfer function with DCI-P3 primaries.
+
+func DisplayP3ToLinearRgb(r, g, b float64) (rl, gl, bl float64) {
+ rl = linearize(r)
+ gl = linearize(g)
+ bl = linearize(b)
+ return
+}
+
+func LinearDisplayP3ToXyz(r, g, b float64) (x, y, z float64) {
+ x = 0.4865709486482162*r + 0.26566769316909306*g + 0.1982172852343625*b
+ y = 0.2289745640697488*r + 0.6917385218365064*g + 0.079286914093745*b
+ z = 0.04511338185890264*g + 1.043944368900976*b
+ return
+}
+
+func XyzToLinearDisplayP3(x, y, z float64) (r, g, b float64) {
+ r = 2.493496911941425*x - 0.9313836179191239*y - 0.40271078445071684*z
+ g = -0.8294889695615747*x + 1.7626640603183463*y + 0.023624685841943577*z
+ b = 0.035845830243784335*x - 0.07617238926804182*y + 0.9568845240076872*z
+ return
+}
+
+func DisplayP3(r, g, b float64) Color {
+ rl, gl, bl := DisplayP3ToLinearRgb(r, g, b)
+ x, y, z := LinearDisplayP3ToXyz(rl, gl, bl)
+ return Xyz(x, y, z)
+}
+
+func (col Color) DisplayP3() (r, g, b float64) {
+ x, y, z := col.Xyz()
+ rl, gl, bl := XyzToLinearDisplayP3(x, y, z)
+ r = delinearize(rl)
+ g = delinearize(gl)
+ b = delinearize(bl)
+ return
+}
+
+// BlendDisplayP3 blends two colors in the Display P3 color-space.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendDisplayP3(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.DisplayP3()
+ r2, g2, b2 := c2.DisplayP3()
+ return DisplayP3(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1))
+}
+
+/// A98 RGB ///
+///////////////
+// Adobe RGB (1998) color space.
+
+func linearizeA98(v float64) float64 {
+ sign := 1.0
+ if v < 0 {
+ sign = -1.0
+ v = -v
+ }
+ return sign * math.Pow(v, 563.0/256.0)
+}
+
+func delinearizeA98(v float64) float64 {
+ sign := 1.0
+ if v < 0 {
+ sign = -1.0
+ v = -v
+ }
+ return sign * math.Pow(v, 256.0/563.0)
+}
+
+func A98RgbToLinearRgb(r, g, b float64) (rl, gl, bl float64) {
+ rl = linearizeA98(r)
+ gl = linearizeA98(g)
+ bl = linearizeA98(b)
+ return
+}
+
+func LinearA98RgbToXyz(r, g, b float64) (x, y, z float64) {
+ x = 0.5766690429101305*r + 0.1855582379065463*g + 0.1882286462349947*b
+ y = 0.29734497525053605*r + 0.6273635662554661*g + 0.07529145849399788*b
+ z = 0.02703136138641234*r + 0.07068885253582723*g + 0.9913375368376388*b
+ return
+}
+
+func XyzToLinearA98Rgb(x, y, z float64) (r, g, b float64) {
+ r = 2.0415879038107327*x - 0.5650069742788597*y - 0.34473135077832956*z
+ g = -0.9692436362808795*x + 1.8759675015077202*y + 0.04155505740717559*z
+ b = 0.013444280632031142*x - 0.11836239223101838*y + 1.0151749943912054*z
+ return
+}
+
+func A98Rgb(r, g, b float64) Color {
+ rl, gl, bl := A98RgbToLinearRgb(r, g, b)
+ x, y, z := LinearA98RgbToXyz(rl, gl, bl)
+ return Xyz(x, y, z)
+}
+
+func (col Color) A98Rgb() (r, g, b float64) {
+ x, y, z := col.Xyz()
+ rl, gl, bl := XyzToLinearA98Rgb(x, y, z)
+ r = delinearizeA98(rl)
+ g = delinearizeA98(gl)
+ b = delinearizeA98(bl)
+ return
+}
+
+// BlendA98Rgb blends two colors in the A98 RGB color-space.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendA98Rgb(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.A98Rgb()
+ r2, g2, b2 := c2.A98Rgb()
+ return A98Rgb(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1))
+}
+
+/// ProPhoto RGB ///
+////////////////////
+// ProPhoto RGB (ROMM RGB) uses D50 illuminant.
+
+func linearizeProPhoto(v float64) float64 {
+ if v <= 16.0/512.0 {
+ return v / 16.0
+ }
+ return math.Pow(v, 1.8)
+}
+
+func delinearizeProPhoto(v float64) float64 {
+ if v < 1.0/512.0 {
+ return 16.0 * v
+ }
+ return math.Pow(v, 1.0/1.8)
+}
+
+func ProPhotoRgbToLinearRgb(r, g, b float64) (rl, gl, bl float64) {
+ rl = linearizeProPhoto(r)
+ gl = linearizeProPhoto(g)
+ bl = linearizeProPhoto(b)
+ return
+}
+
+func LinearProPhotoRgbToXyzD50(r, g, b float64) (x, y, z float64) {
+ x = 0.7977604896723027*r + 0.13518583717574031*g + 0.0313493495815248*b
+ y = 0.2880711282292934*r + 0.7118432178101014*g + 0.00008565396060525902*b
+ z = 0.8251046025104602 * b
+ return
+}
+
+func XyzD50ToLinearProPhotoRgb(x, y, z float64) (r, g, b float64) {
+ r = 1.3457989731028281*x - 0.25558010007997534*y - 0.05110628506753401*z
+ g = -0.5446224939028347*x + 1.5082327413132781*y + 0.02053603239147973*z
+ b = 1.2119675456389454 * z
+ return
+}
+
+func ProPhotoRgb(r, g, b float64) Color {
+ rl, gl, bl := ProPhotoRgbToLinearRgb(r, g, b)
+ x, y, z := LinearProPhotoRgbToXyzD50(rl, gl, bl)
+ return XyzD50(x, y, z)
+}
+
+func (col Color) ProPhotoRgb() (r, g, b float64) {
+ x, y, z := col.XyzD50()
+ rl, gl, bl := XyzD50ToLinearProPhotoRgb(x, y, z)
+ r = delinearizeProPhoto(rl)
+ g = delinearizeProPhoto(gl)
+ b = delinearizeProPhoto(bl)
+ return
+}
+
+// BlendProPhotoRgb blends two colors in the ProPhoto RGB color-space.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendProPhotoRgb(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.ProPhotoRgb()
+ r2, g2, b2 := c2.ProPhotoRgb()
+ return ProPhotoRgb(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1))
+}
+
+/// Rec. 2020 ///
+/////////////////
+// ITU-R BT.2020 color space.
+
+const (
+ rec2020Alpha = 1.09929682680944
+ rec2020Beta = 0.018053968510807
+)
+
+func linearizeRec2020(v float64) float64 {
+ if v < rec2020Beta*4.5 {
+ return v / 4.5
+ }
+ return math.Pow((v+rec2020Alpha-1)/rec2020Alpha, 1.0/0.45)
+}
+
+func delinearizeRec2020(v float64) float64 {
+ if v < rec2020Beta {
+ return 4.5 * v
+ }
+ return rec2020Alpha*math.Pow(v, 0.45) - (rec2020Alpha - 1)
+}
+
+func Rec2020ToLinearRgb(r, g, b float64) (rl, gl, bl float64) {
+ rl = linearizeRec2020(r)
+ gl = linearizeRec2020(g)
+ bl = linearizeRec2020(b)
+ return
+}
+
+func LinearRec2020ToXyz(r, g, b float64) (x, y, z float64) {
+ x = 0.6369580483012914*r + 0.14461690358620832*g + 0.1688809751641721*b
+ y = 0.2627002120112671*r + 0.6779980715188708*g + 0.05930171646986196*b
+ z = 0.028072693049087428*g + 1.0609850577107909*b
+ return
+}
+
+func XyzToLinearRec2020(x, y, z float64) (r, g, b float64) {
+ r = 1.7166511879712674*x - 0.35567078377639233*y - 0.25336628137365974*z
+ g = -0.666684351832489*x + 1.616481236634939*y + 0.0157685458139402*z
+ b = 0.017639857445310783*x - 0.042770613257808524*y + 0.9421031212354738*z
+ return
+}
+
+func Rec2020(r, g, b float64) Color {
+ rl, gl, bl := Rec2020ToLinearRgb(r, g, b)
+ x, y, z := LinearRec2020ToXyz(rl, gl, bl)
+ return Xyz(x, y, z)
+}
+
+func (col Color) Rec2020() (r, g, b float64) {
+ x, y, z := col.Xyz()
+ rl, gl, bl := XyzToLinearRec2020(x, y, z)
+ r = delinearizeRec2020(rl)
+ g = delinearizeRec2020(gl)
+ b = delinearizeRec2020(bl)
+ return
+}
+
+// BlendRec2020 blends two colors in the Rec. 2020 color-space.
+// t == 0 results in c1, t == 1 results in c2
+func (c1 Color) BlendRec2020(c2 Color, t float64) Color {
+ r1, g1, b1 := c1.Rec2020()
+ r2, g2, b2 := c2.Rec2020()
+ return Rec2020(
+ r1+t*(r2-r1),
+ g1+t*(g2-g1),
+ b1+t*(b2-b1))
+}
diff --git a/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go b/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go
index c3112107..1e439175 100644
--- a/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go
+++ b/vendor/github.com/manuelarte/funcorder/analyzer/analyzer.go
@@ -14,6 +14,7 @@ const (
ConstructorCheckName = "constructor"
StructMethodCheckName = "struct-method"
AlphabeticalCheckName = "alphabetical"
+ FunctionCheckName = "function"
)
func NewAnalyzer() *analysis.Analyzer {
@@ -33,6 +34,8 @@ func NewAnalyzer() *analysis.Analyzer {
"Checks if the exported methods of a structure are placed before the unexported ones.")
a.Flags.BoolVar(&f.alphabeticalCheck, AlphabeticalCheckName, false,
"Checks if the constructors and/or structure methods are sorted alphabetically.")
+ a.Flags.BoolVar(&f.functionCheck, FunctionCheckName, false,
+ "Checks that exported functions are placed before unexported functions.")
return a
}
@@ -41,9 +44,16 @@ type funcorder struct {
constructorCheck bool
structMethodCheck bool
alphabeticalCheck bool
+ functionCheck bool
}
func (f *funcorder) run(pass *analysis.Pass) (any, error) {
+ insp, found := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+ if !found {
+ //nolint:nilnil // impossible case.
+ return nil, nil
+ }
+
var enabledCheckers internal.Feature
if f.constructorCheck {
enabledCheckers.Enable(internal.ConstructorCheck)
@@ -57,14 +67,12 @@ func (f *funcorder) run(pass *analysis.Pass) (any, error) {
enabledCheckers.Enable(internal.AlphabeticalCheck)
}
- fp := internal.NewFileProcessor(pass.Fset, enabledCheckers)
-
- insp, found := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
- if !found {
- //nolint:nilnil // impossible case.
- return nil, nil
+ if f.functionCheck {
+ enabledCheckers.Enable(internal.FunctionCheck)
}
+ fp := internal.NewFileProcessor(enabledCheckers)
+
nodeFilter := []ast.Node{
(*ast.File)(nil),
(*ast.FuncDecl)(nil),
@@ -74,23 +82,18 @@ func (f *funcorder) run(pass *analysis.Pass) (any, error) {
insp.Preorder(nodeFilter, func(n ast.Node) {
switch node := n.(type) {
case *ast.File:
- for _, report := range fp.Analyze() {
- pass.Report(report)
- }
-
- fp.NewFileNode(node)
+ fp.Analyze(pass)
+ fp.ResetStructs()
case *ast.FuncDecl:
- fp.NewFuncDecl(node)
+ fp.AddFuncDecl(node)
case *ast.TypeSpec:
- fp.NewTypeSpec(node)
+ fp.AddTypeSpec(node)
}
})
- for _, report := range fp.Analyze() {
- pass.Report(report)
- }
+ fp.Analyze(pass)
//nolint:nilnil //any, error
return nil, nil
diff --git a/vendor/github.com/manuelarte/funcorder/internal/astutils.go b/vendor/github.com/manuelarte/funcorder/internal/astutils.go
deleted file mode 100644
index af7fa8c8..00000000
--- a/vendor/github.com/manuelarte/funcorder/internal/astutils.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package internal
-
-import (
- "bytes"
- "go/ast"
- "go/format"
- "go/token"
- "strings"
-)
-
-func FuncCanBeConstructor(n *ast.FuncDecl) bool {
- if !n.Name.IsExported() || n.Recv != nil {
- return false
- }
-
- if n.Type.Results == nil || len(n.Type.Results.List) == 0 {
- return false
- }
-
- for _, prefix := range []string{"new", "must"} {
- if strings.HasPrefix(strings.ToLower(n.Name.Name), prefix) &&
- len(n.Name.Name) > len(prefix) { // TODO(ldez): bug if the name is just `New`.
- return true
- }
- }
-
- return false
-}
-
-func FuncIsMethod(n *ast.FuncDecl) (*ast.Ident, bool) {
- if n.Recv == nil {
- return nil, false
- }
-
- if len(n.Recv.List) != 1 {
- return nil, false
- }
-
- if recv, ok := GetIdent(n.Recv.List[0].Type); ok {
- return recv, true
- }
-
- return nil, false
-}
-
-func GetIdent(expr ast.Expr) (*ast.Ident, bool) {
- switch exp := expr.(type) {
- case *ast.StarExpr:
- return GetIdent(exp.X)
-
- case *ast.Ident:
- return exp, true
-
- default:
- return nil, false
- }
-}
-
-// GetStartingPos returns the token starting position of the function
-// taking into account if there are comments.
-func GetStartingPos(function *ast.FuncDecl) token.Pos {
- startingPos := function.Pos()
- if function.Doc != nil {
- startingPos = function.Doc.Pos()
- }
-
- return startingPos
-}
-
-// NodeToBytes convert the ast.Node in bytes.
-func NodeToBytes(fset *token.FileSet, node ast.Node) ([]byte, error) {
- var buf bytes.Buffer
- if err := format.Node(&buf, fset, node); err != nil {
- return nil, err
- }
-
- return buf.Bytes(), nil
-}
-
-// SplitExportedUnexported split functions/methods based on whether they are exported or not.
-//
-//nolint:nonamedreturns // names serve as documentation
-func SplitExportedUnexported(funcDecls []*ast.FuncDecl) (exported, unexported []*ast.FuncDecl) {
- for _, f := range funcDecls {
- if f.Name.IsExported() {
- exported = append(exported, f)
- } else {
- unexported = append(unexported, f)
- }
- }
-
- return exported, unexported
-}
diff --git a/vendor/github.com/manuelarte/funcorder/internal/features.go b/vendor/github.com/manuelarte/funcorder/internal/features.go
index 55d5caba..7012a688 100644
--- a/vendor/github.com/manuelarte/funcorder/internal/features.go
+++ b/vendor/github.com/manuelarte/funcorder/internal/features.go
@@ -4,6 +4,7 @@ const (
ConstructorCheck Feature = 1 << iota
StructMethodCheck
AlphabeticalCheck
+ FunctionCheck
)
type Feature uint8
diff --git a/vendor/github.com/manuelarte/funcorder/internal/file_processor.go b/vendor/github.com/manuelarte/funcorder/internal/file_processor.go
index 88ae00f2..9276c4a0 100644
--- a/vendor/github.com/manuelarte/funcorder/internal/file_processor.go
+++ b/vendor/github.com/manuelarte/funcorder/internal/file_processor.go
@@ -2,69 +2,102 @@ package internal
import (
"go/ast"
- "go/token"
"golang.org/x/tools/go/analysis"
)
// FileProcessor Holder to store all the functions that are potential to be constructors and all the structs.
type FileProcessor struct {
- fset *token.FileSet
- structs map[string]*StructHolder
- features Feature
+ structs map[string]*StructHolder
+ features Feature
+ topLevelFuncs []*ast.FuncDecl
}
// NewFileProcessor creates a new file processor.
-func NewFileProcessor(fset *token.FileSet, checkers Feature) *FileProcessor {
+func NewFileProcessor(checkers Feature) *FileProcessor {
return &FileProcessor{
- fset: fset,
structs: make(map[string]*StructHolder),
features: checkers,
}
}
// Analyze check whether the order of the methods in the constructor is correct.
-func (fp *FileProcessor) Analyze() []analysis.Diagnostic {
- var reports []analysis.Diagnostic
-
+func (fp *FileProcessor) Analyze(pass *analysis.Pass) {
for _, sh := range fp.structs {
// filter out structs that are not declared inside that file
if sh.Struct != nil {
- reports = append(reports, sh.Analyze()...)
+ sh.Analyze(pass)
}
}
- return reports
+ if fp.features.IsEnabled(FunctionCheck) {
+ fp.analyzeFunctions(pass)
+ }
}
-func (fp *FileProcessor) NewFileNode(_ *ast.File) {
+func (fp *FileProcessor) ResetStructs() {
fp.structs = make(map[string]*StructHolder)
+ fp.topLevelFuncs = nil
}
-func (fp *FileProcessor) NewFuncDecl(n *ast.FuncDecl) {
- if sc, ok := NewStructConstructor(n); ok {
- fp.addConstructor(sc)
+func (fp *FileProcessor) AddFuncDecl(n *ast.FuncDecl) {
+ if fp.features.IsEnabled(FunctionCheck) && n.Recv == nil {
+ fp.topLevelFuncs = append(fp.topLevelFuncs, n)
+ }
+
+ if sc := NewStructConstructor(n); sc != nil {
+ sh := fp.getOrCreate(sc.StructReturn.Name)
+ sh.Constructors = append(sh.Constructors, sc.Constructor)
+
return
}
- if st, ok := FuncIsMethod(n); ok {
- fp.addMethod(st.Name, n)
+ if st := funcIsMethod(n); st != nil {
+ sh := fp.getOrCreate(st.Name)
+ sh.StructMethods = append(sh.StructMethods, n)
}
}
-func (fp *FileProcessor) NewTypeSpec(n *ast.TypeSpec) {
+func (fp *FileProcessor) AddTypeSpec(n *ast.TypeSpec) {
sh := fp.getOrCreate(n.Name.Name)
sh.Struct = n
}
-func (fp *FileProcessor) addConstructor(sc StructConstructor) {
- sh := fp.getOrCreate(sc.GetStructReturn().Name)
- sh.AddConstructor(sc.GetConstructor())
-}
+// analyzeFunctions reports every unexported top-level function that appears
+// before the last exported top-level function in source order.
+// The `init` function is excluded from this check.
+func (fp *FileProcessor) analyzeFunctions(pass *analysis.Pass) {
+ var lastExported *ast.FuncDecl
+
+ for _, fn := range fp.topLevelFuncs {
+ if fn.Name.Name == "init" {
+ continue
+ }
+
+ if !fn.Name.IsExported() {
+ continue
+ }
+
+ if lastExported == nil || fn.Pos() > lastExported.Pos() {
+ lastExported = fn
+ }
+ }
+
+ if lastExported == nil {
+ return
+ }
-func (fp *FileProcessor) addMethod(st string, n *ast.FuncDecl) {
- sh := fp.getOrCreate(st)
- sh.AddMethod(n)
+ for _, fn := range fp.topLevelFuncs {
+ if fn.Name.Name == "init" {
+ continue
+ }
+
+ if fn.Name.IsExported() || fn.Pos() >= lastExported.Pos() {
+ continue
+ }
+
+ reportUnexportedFuncBeforeExportedFunc(pass, fn, lastExported)
+ }
}
func (fp *FileProcessor) getOrCreate(structName string) *StructHolder {
@@ -73,10 +106,34 @@ func (fp *FileProcessor) getOrCreate(structName string) *StructHolder {
}
created := &StructHolder{
- Fset: fp.fset,
Features: fp.features,
}
fp.structs[structName] = created
return created
}
+
+func funcIsMethod(n *ast.FuncDecl) *ast.Ident {
+ if n.Recv == nil {
+ return nil
+ }
+
+ if len(n.Recv.List) != 1 {
+ return nil
+ }
+
+ return getIdent(n.Recv.List[0].Type)
+}
+
+func getIdent(expr ast.Expr) *ast.Ident {
+ switch exp := expr.(type) {
+ case *ast.StarExpr:
+ return getIdent(exp.X)
+
+ case *ast.Ident:
+ return exp
+
+ default:
+ return nil
+ }
+}
diff --git a/vendor/github.com/manuelarte/funcorder/internal/diag.go b/vendor/github.com/manuelarte/funcorder/internal/reports.go
similarity index 58%
rename from vendor/github.com/manuelarte/funcorder/internal/diag.go
rename to vendor/github.com/manuelarte/funcorder/internal/reports.go
index faf2ffdd..350ac05e 100644
--- a/vendor/github.com/manuelarte/funcorder/internal/diag.go
+++ b/vendor/github.com/manuelarte/funcorder/internal/reports.go
@@ -7,63 +7,72 @@ import (
"golang.org/x/tools/go/analysis"
)
-func NewConstructorNotAfterStructType(structSpec *ast.TypeSpec, constructor *ast.FuncDecl) analysis.Diagnostic {
- return analysis.Diagnostic{
+func reportConstructorNotAfterStructType(pass *analysis.Pass, structSpec *ast.TypeSpec, constructor *ast.FuncDecl) {
+ pass.Report(analysis.Diagnostic{
Pos: constructor.Pos(),
Message: fmt.Sprintf("constructor %q for struct %q should be placed after the struct declaration",
constructor.Name, structSpec.Name),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-constructors-functions-are-placed-after-struct-declaration", //nolint:lll // url
- }
+ })
}
-func NewConstructorNotBeforeStructMethod(
+func reportConstructorNotBeforeStructMethod(
+ pass *analysis.Pass,
structSpec *ast.TypeSpec,
- constructor *ast.FuncDecl,
- method *ast.FuncDecl,
-) analysis.Diagnostic {
- return analysis.Diagnostic{
+ constructor, method *ast.FuncDecl,
+) {
+ pass.Report(analysis.Diagnostic{
Pos: constructor.Pos(),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-constructors-functions-are-placed-after-struct-declaration", //nolint:lll // url
Message: fmt.Sprintf("constructor %q for struct %q should be placed before struct method %q",
constructor.Name, structSpec.Name, method.Name),
- }
+ })
}
-func NewAdjacentConstructorsNotSortedAlphabetically(
+func reportAdjacentConstructorsNotSortedAlphabetically(
+ pass *analysis.Pass,
structSpec *ast.TypeSpec,
- constructorNotSorted *ast.FuncDecl,
- otherConstructorNotSorted *ast.FuncDecl,
-) analysis.Diagnostic {
- return analysis.Diagnostic{
+ constructorNotSorted, otherConstructorNotSorted *ast.FuncDecl,
+) {
+ pass.Report(analysis.Diagnostic{
Pos: otherConstructorNotSorted.Pos(),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-constructorsmethods-are-sorted-alphabetically",
Message: fmt.Sprintf("constructor %q for struct %q should be placed before constructor %q",
otherConstructorNotSorted.Name, structSpec.Name, constructorNotSorted.Name),
- }
+ })
}
-func NewUnexportedMethodBeforeExportedForStruct(
+func reportUnexportedMethodBeforeExportedForStruct(
+ pass *analysis.Pass,
structSpec *ast.TypeSpec,
- privateMethod *ast.FuncDecl,
- publicMethod *ast.FuncDecl,
-) analysis.Diagnostic {
- return analysis.Diagnostic{
+ privateMethod, publicMethod *ast.FuncDecl,
+) {
+ pass.Report(analysis.Diagnostic{
Pos: privateMethod.Pos(),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-exported-methods-are-placed-before-unexported-methods", //nolint:lll // url
Message: fmt.Sprintf("unexported method %q for struct %q should be placed after the exported method %q",
privateMethod.Name, structSpec.Name, publicMethod.Name),
- }
+ })
}
-func NewAdjacentStructMethodsNotSortedAlphabetically(
+func reportAdjacentStructMethodsNotSortedAlphabetically(
+ pass *analysis.Pass,
structSpec *ast.TypeSpec,
- method *ast.FuncDecl,
- otherMethod *ast.FuncDecl,
-) analysis.Diagnostic {
- return analysis.Diagnostic{
+ method, otherMethod *ast.FuncDecl,
+) {
+ pass.Report(analysis.Diagnostic{
Pos: otherMethod.Pos(),
URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-constructorsmethods-are-sorted-alphabetically",
Message: fmt.Sprintf("method %q for struct %q should be placed before method %q",
otherMethod.Name, structSpec.Name, method.Name),
- }
+ })
+}
+
+func reportUnexportedFuncBeforeExportedFunc(pass *analysis.Pass, unexportedFunc, exportedFunc *ast.FuncDecl) {
+ pass.Report(analysis.Diagnostic{
+ Pos: unexportedFunc.Pos(),
+ URL: "https://github.com/manuelarte/funcorder?tab=readme-ov-file#check-exported-functions-are-placed-before-unexported-functions", //nolint:lll // url
+ Message: fmt.Sprintf("unexported function %q should be placed after the exported function %q",
+ unexportedFunc.Name, exportedFunc.Name),
+ })
}
diff --git a/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go b/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go
index fc4b252d..c036fc13 100644
--- a/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go
+++ b/vendor/github.com/manuelarte/funcorder/internal/struct_constructor.go
@@ -2,36 +2,47 @@ package internal
import (
"go/ast"
+ "strings"
)
type StructConstructor struct {
- constructor *ast.FuncDecl
- structReturn *ast.Ident
+ Constructor *ast.FuncDecl
+ StructReturn *ast.Ident
}
-func NewStructConstructor(funcDec *ast.FuncDecl) (StructConstructor, bool) {
- if !FuncCanBeConstructor(funcDec) {
- return StructConstructor{}, false
+func NewStructConstructor(funcDec *ast.FuncDecl) *StructConstructor {
+ if !funcCanBeConstructor(funcDec) {
+ return nil
}
expr := funcDec.Type.Results.List[0].Type
- returnType, ok := GetIdent(expr)
- if !ok {
- return StructConstructor{}, false
+ returnType := getIdent(expr)
+ if returnType == nil {
+ return nil
}
- return StructConstructor{
- constructor: funcDec,
- structReturn: returnType,
- }, true
+ return &StructConstructor{
+ Constructor: funcDec,
+ StructReturn: returnType,
+ }
}
-// GetStructReturn Return the struct linked to this "constructor".
-func (sc StructConstructor) GetStructReturn() *ast.Ident {
- return sc.structReturn
-}
+func funcCanBeConstructor(n *ast.FuncDecl) bool {
+ if !n.Name.IsExported() || n.Recv != nil {
+ return false
+ }
+
+ if n.Type.Results == nil || len(n.Type.Results.List) == 0 {
+ return false
+ }
+
+ for _, prefix := range []string{"new", "must"} {
+ if strings.HasPrefix(strings.ToLower(n.Name.Name), prefix) &&
+ len(n.Name.Name) > len(prefix) { // TODO(ldez): bug if the name is just `New`.
+ return true
+ }
+ }
-func (sc StructConstructor) GetConstructor() *ast.FuncDecl {
- return sc.constructor
+ return false
}
diff --git a/vendor/github.com/manuelarte/funcorder/internal/structholder.go b/vendor/github.com/manuelarte/funcorder/internal/structholder.go
index 424b2ddd..30042211 100644
--- a/vendor/github.com/manuelarte/funcorder/internal/structholder.go
+++ b/vendor/github.com/manuelarte/funcorder/internal/structholder.go
@@ -3,21 +3,13 @@ package internal
import (
"cmp"
"go/ast"
- "go/token"
"slices"
"golang.org/x/tools/go/analysis"
)
-type (
- ExportedMethods []*ast.FuncDecl
- UnexportedMethods []*ast.FuncDecl
-)
-
// StructHolder contains all the information around a Go struct.
type StructHolder struct {
- // The fileset
- Fset *token.FileSet
// The features to be analyzed
Features Feature
@@ -31,59 +23,42 @@ type StructHolder struct {
StructMethods []*ast.FuncDecl
}
-func (sh *StructHolder) AddConstructor(fn *ast.FuncDecl) {
- sh.Constructors = append(sh.Constructors, fn)
-}
-
-func (sh *StructHolder) AddMethod(fn *ast.FuncDecl) {
- sh.StructMethods = append(sh.StructMethods, fn)
-}
-
// Analyze applies the linter to the struct holder.
-func (sh *StructHolder) Analyze() []analysis.Diagnostic {
+func (sh *StructHolder) Analyze(pass *analysis.Pass) {
// TODO maybe sort constructors and then report also, like NewXXX before MustXXX
slices.SortFunc(sh.StructMethods, func(a, b *ast.FuncDecl) int {
return cmp.Compare(a.Pos(), b.Pos())
})
- var reports []analysis.Diagnostic
+ // TODO also check that the methods are declared after the struct
if sh.Features.IsEnabled(ConstructorCheck) {
- reports = append(reports, sh.analyzeConstructor()...)
+ sh.analyzeConstructor(pass)
}
if sh.Features.IsEnabled(StructMethodCheck) {
- reports = append(reports, sh.analyzeStructMethod()...)
+ sh.analyzeStructMethod(pass)
}
-
- // TODO also check that the methods are declared after the struct
- return reports
}
-func (sh *StructHolder) analyzeConstructor() []analysis.Diagnostic {
- var reports []analysis.Diagnostic
-
+func (sh *StructHolder) analyzeConstructor(pass *analysis.Pass) {
for i, constructor := range sh.Constructors {
if constructor.Pos() < sh.Struct.Pos() {
- reports = append(reports, NewConstructorNotAfterStructType(sh.Struct, constructor))
+ reportConstructorNotAfterStructType(pass, sh.Struct, constructor)
}
if len(sh.StructMethods) > 0 && constructor.Pos() > sh.StructMethods[0].Pos() {
- reports = append(reports, NewConstructorNotBeforeStructMethod(sh.Struct, constructor, sh.StructMethods[0]))
+ reportConstructorNotBeforeStructMethod(pass, sh.Struct, constructor, sh.StructMethods[0])
}
if sh.Features.IsEnabled(AlphabeticalCheck) &&
i < len(sh.Constructors)-1 && sh.Constructors[i].Name.Name > sh.Constructors[i+1].Name.Name {
- reports = append(reports,
- NewAdjacentConstructorsNotSortedAlphabetically(sh.Struct, sh.Constructors[i], sh.Constructors[i+1]),
- )
+ reportAdjacentConstructorsNotSortedAlphabetically(pass, sh.Struct, sh.Constructors[i], sh.Constructors[i+1])
}
}
-
- return reports
}
-func (sh *StructHolder) analyzeStructMethod() []analysis.Diagnostic {
+func (sh *StructHolder) analyzeStructMethod(pass *analysis.Pass) {
var lastExportedMethod *ast.FuncDecl
for _, m := range sh.StructMethods {
@@ -100,42 +75,46 @@ func (sh *StructHolder) analyzeStructMethod() []analysis.Diagnostic {
}
}
- var reports []analysis.Diagnostic
-
if lastExportedMethod != nil {
for _, m := range sh.StructMethods {
if m.Name.IsExported() || m.Pos() >= lastExportedMethod.Pos() {
continue
}
- reports = append(reports, NewUnexportedMethodBeforeExportedForStruct(sh.Struct, m, lastExportedMethod))
+ reportUnexportedMethodBeforeExportedForStruct(pass, sh.Struct, m, lastExportedMethod)
}
}
if sh.Features.IsEnabled(AlphabeticalCheck) {
- exported, unexported := SplitExportedUnexported(sh.StructMethods)
- reports = slices.Concat(reports,
- sortDiagnostics(sh.Struct, exported),
- sortDiagnostics(sh.Struct, unexported),
- )
+ exported, unexported := splitExportedUnexported(sh.StructMethods)
+ sh.sortDiagnostics(pass, exported)
+ sh.sortDiagnostics(pass, unexported)
}
-
- return reports
}
-func sortDiagnostics(typeSpec *ast.TypeSpec, funcDecls []*ast.FuncDecl) []analysis.Diagnostic {
- var reports []analysis.Diagnostic
-
+func (sh *StructHolder) sortDiagnostics(pass *analysis.Pass, funcDecls []*ast.FuncDecl) {
for i := range funcDecls {
if i >= len(funcDecls)-1 {
continue
}
if funcDecls[i].Name.Name > funcDecls[i+1].Name.Name {
- reports = append(reports,
- NewAdjacentStructMethodsNotSortedAlphabetically(typeSpec, funcDecls[i], funcDecls[i+1]))
+ reportAdjacentStructMethodsNotSortedAlphabetically(pass, sh.Struct, funcDecls[i], funcDecls[i+1])
+ }
+ }
+}
+
+// splitExportedUnexported split functions/methods based on whether they are exported or not.
+//
+//nolint:nonamedreturns // names serve as documentation
+func splitExportedUnexported(funcDecls []*ast.FuncDecl) (exported, unexported []*ast.FuncDecl) {
+ for _, f := range funcDecls {
+ if f.Name.IsExported() {
+ exported = append(exported, f)
+ } else {
+ unexported = append(unexported, f)
}
}
- return reports
+ return exported, unexported
}
diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go
index 2df7b859..426a409c 100644
--- a/vendor/github.com/mattn/go-colorable/colorable_windows.go
+++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go
@@ -5,13 +5,13 @@ package colorable
import (
"bytes"
+ syscall "golang.org/x/sys/windows"
"io"
"math"
"os"
"strconv"
"strings"
"sync"
- syscall "golang.org/x/sys/windows"
"unsafe"
"github.com/mattn/go-isatty"
@@ -93,6 +93,7 @@ type writer struct {
handle syscall.Handle
althandle syscall.Handle
oldattr word
+ curattr word
oldpos coord
rest bytes.Buffer
mutex sync.Mutex
@@ -112,7 +113,7 @@ func NewColorable(file *os.File) io.Writer {
var csbi consoleScreenBufferInfo
handle := syscall.Handle(file.Fd())
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
- return &writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}}
+ return &writer{out: file, handle: handle, oldattr: csbi.attributes, curattr: csbi.attributes, oldpos: coord{0, 0}}
}
return file
}
@@ -438,7 +439,11 @@ func (w *writer) Write(data []byte) (n int, err error) {
w.mutex.Lock()
defer w.mutex.Unlock()
var csbi consoleScreenBufferInfo
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
+
+ if w.rest.Len() == 0 && bytes.IndexByte(data, 0x1b) == -1 {
+ w.out.Write(data)
+ return len(data), nil
+ }
handle := w.handle
@@ -517,7 +522,7 @@ loop:
w.rest.Reset()
break
}
- buf.Write([]byte(string(c)))
+ buf.WriteByte(c)
}
if m == 0 {
break loop
@@ -678,11 +683,11 @@ loop:
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'm':
- procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
- attr := csbi.attributes
+ attr := w.curattr
cs := buf.String()
if cs == "" {
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
+ w.curattr = w.oldattr
continue
}
token := strings.Split(cs, ";")
@@ -814,9 +819,12 @@ loop:
attr |= backgroundBlue
}
}
- procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
}
}
+ if attr != w.curattr {
+ procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
+ w.curattr = attr
+ }
case 'h':
var ci consoleCursorInfo
cs := buf.String()
@@ -834,6 +842,8 @@ loop:
w.althandle = syscall.Handle(h)
if w.althandle != 0 {
handle = w.althandle
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+ w.curattr = csbi.attributes
}
}
}
@@ -853,6 +863,8 @@ loop:
syscall.CloseHandle(w.althandle)
w.althandle = 0
handle = w.handle
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+ w.curattr = csbi.attributes
}
}
case 's':
diff --git a/vendor/github.com/mattn/go-runewidth/SECURITY.md b/vendor/github.com/mattn/go-runewidth/SECURITY.md
new file mode 100644
index 00000000..a6898ee7
--- /dev/null
+++ b/vendor/github.com/mattn/go-runewidth/SECURITY.md
@@ -0,0 +1,25 @@
+# Security Policy
+
+## Supported Versions
+
+The following versions of go-runewidth are currently supported with
+security updates.
+
+| Version | Supported |
+| -------- | ------------------ |
+| 0.0.23 | :white_check_mark: |
+| < 0.0.23 | :x: |
+
+## Reporting a Vulnerability
+
+If you discover a security vulnerability in go-runewidth, please report it
+privately via GitHub's "Report a vulnerability" feature on the Security tab
+of the repository (https://github.com/mattn/go-runewidth/security), or by
+emailing the maintainer at mattn.jp@gmail.com.
+
+Please include a description of the issue, reproduction steps, and the
+affected version. You can expect an initial response within one week. If
+the vulnerability is accepted, a fix will be prepared and a new release
+will be published; you will be credited in the release notes unless you
+request otherwise. If the report is declined, you will receive an
+explanation of the reasoning.
diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go
index 0edabac3..6b958fdd 100644
--- a/vendor/github.com/mattn/go-runewidth/runewidth.go
+++ b/vendor/github.com/mattn/go-runewidth/runewidth.go
@@ -2,7 +2,9 @@ package runewidth
import (
"os"
+ "sort"
"strings"
+ "unicode/utf8"
"github.com/clipperhouse/uax29/v2/graphemes"
)
@@ -23,10 +25,54 @@ var (
}
)
+var (
+ zerowidth table // combining + nonprint merged for faster zero-width lookup
+ widewidth table // ambiguous + doublewidth merged for EA path
+ eastAsianWidth widthTable
+ eastAsianWidth0 [0x300]byte
+)
+
func init() {
+ zerowidth = mergeIntervals(combining, nonprint)
+ widewidth = mergeIntervals(ambiguous, doublewidth)
+ eastAsianWidth = makeWidthTable(zerowidth, widewidth)
+ for r := range eastAsianWidth0 {
+ eastAsianWidth0[r] = byte(runeWidthEastAsian(rune(r)))
+ }
handleEnv()
}
+func mergeIntervals(t1, t2 table) table {
+ merged := make(table, 0, len(t1)+len(t2))
+ i, j := 0, 0
+ for i < len(t1) && j < len(t2) {
+ if t1[i].first <= t2[j].first {
+ merged = append(merged, t1[i])
+ i++
+ } else {
+ merged = append(merged, t2[j])
+ j++
+ }
+ }
+ merged = append(merged, t1[i:]...)
+ merged = append(merged, t2[j:]...)
+ if len(merged) == 0 {
+ return merged
+ }
+ result := merged[:1]
+ for _, iv := range merged[1:] {
+ last := &result[len(result)-1]
+ if iv.first <= last.last+1 {
+ if iv.last > last.last {
+ last.last = iv.last
+ }
+ } else {
+ result = append(result, iv)
+ }
+ }
+ return result
+}
+
func handleEnv() {
env := os.Getenv("RUNEWIDTH_EASTASIAN")
if env == "" {
@@ -51,15 +97,14 @@ type interval struct {
type table []interval
-func inTables(r rune, ts ...table) bool {
- for _, t := range ts {
- if inTable(r, t) {
- return true
- }
- }
- return false
+type widthInterval struct {
+ first rune
+ last rune
+ width byte
}
+type widthTable []widthInterval
+
func inTable(r rune, t table) bool {
if r < t[0].first {
return false
@@ -86,6 +131,71 @@ func inTable(r rune, t table) bool {
return false
}
+func makeWidthTable(zero, two table) widthTable {
+ wt := make(widthTable, 0, len(zero)+len(two))
+ zi := 0
+ for _, iv := range two {
+ start := iv.first
+ for zi < len(zero) && zero[zi].last < start {
+ zi++
+ }
+ for i := zi; i < len(zero) && zero[i].first <= iv.last; i++ {
+ if start < zero[i].first {
+ wt = append(wt, widthInterval{start, zero[i].first - 1, 2})
+ }
+ if start <= zero[i].last {
+ start = zero[i].last + 1
+ }
+ if start > iv.last {
+ break
+ }
+ }
+ if start <= iv.last {
+ wt = append(wt, widthInterval{start, iv.last, 2})
+ }
+ }
+ for _, iv := range zero {
+ wt = append(wt, widthInterval{iv.first, iv.last, 0})
+ }
+ sort.Slice(wt, func(i, j int) bool {
+ return wt[i].first < wt[j].first
+ })
+ return wt
+}
+
+func inWidthTable(r rune, t widthTable) (int, bool) {
+ if r < t[0].first {
+ return 0, false
+ }
+ if r > t[len(t)-1].last {
+ return 0, false
+ }
+
+ bot := 0
+ top := len(t) - 1
+ for top >= bot {
+ mid := (bot + top) >> 1
+
+ switch {
+ case t[mid].last < r:
+ bot = mid + 1
+ case t[mid].first > r:
+ top = mid - 1
+ default:
+ return int(t[mid].width), true
+ }
+ }
+
+ return 0, false
+}
+
+func runeWidthEastAsian(r rune) int {
+ if w, ok := inWidthTable(r, eastAsianWidth); ok {
+ return w
+ }
+ return 1
+}
+
var private = table{
{0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD},
}
@@ -123,36 +233,35 @@ func (c *Condition) RuneWidth(r rune) int {
}
// optimized version, verified by TestRuneWidthChecksums()
if !c.EastAsianWidth {
- switch {
- case r < 0x20:
- return 0
- case (r >= 0x7F && r <= 0x9F) || r == 0xAD: // nonprint
+ if r < 0x20 {
return 0
- case r < 0x300:
- return 1
- case inTable(r, narrow):
- return 1
- case inTables(r, nonprint, combining):
+ }
+ if (r >= 0x7F && r <= 0x9F) || r == 0xAD { // nonprint
return 0
- case inTable(r, doublewidth):
- return 2
- default:
+ }
+ if r < 0x300 {
return 1
}
- } else {
switch {
- case inTables(r, nonprint, combining):
+ case inTable(r, zerowidth):
return 0
- case inTable(r, narrow):
- return 1
- case inTables(r, ambiguous, doublewidth):
- return 2
- case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow):
+ case inTable(r, doublewidth):
return 2
default:
return 1
}
}
+
+ if r < 0x300 {
+ return int(eastAsianWidth0[r])
+ }
+ if w, ok := inWidthTable(r, eastAsianWidth); ok {
+ return w
+ }
+ if !c.StrictEmojiNeutral && inTable(r, emoji) {
+ return 2
+ }
+ return 1
}
// CreateLUT will create an in-memory lookup table of 557056 bytes for faster operation.
@@ -178,6 +287,33 @@ func (c *Condition) CreateLUT() {
// StringWidth return width as you can see
func (c *Condition) StringWidth(s string) (width int) {
+ if len(s) == 1 {
+ b := s[0]
+ if b < 0x20 || b == 0x7F {
+ return 0
+ }
+ return 1
+ }
+ if len(s) > 0 && len(s) <= utf8.UTFMax {
+ r, size := utf8.DecodeRuneInString(s)
+ if size == len(s) {
+ return c.RuneWidth(r)
+ }
+ }
+ // ASCII fast path: no grapheme clustering needed for pure ASCII
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ if b >= 0x80 {
+ goto graphemes
+ }
+ if b >= 0x20 && b != 0x7F {
+ width++
+ }
+ }
+ return
+
+graphemes:
+ width = 0
g := graphemes.FromString(s)
for g.Next() {
var chWidth int
@@ -257,24 +393,25 @@ func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
// Wrap return string wrapped with w cells
func (c *Condition) Wrap(s string, w int) string {
width := 0
- out := ""
+ var out strings.Builder
+ out.Grow(len(s) + len(s)/w + 1)
for _, r := range s {
cw := c.RuneWidth(r)
if r == '\n' {
- out += string(r)
+ out.WriteRune(r)
width = 0
continue
} else if width+cw > w {
- out += "\n"
+ out.WriteByte('\n')
width = 0
- out += string(r)
+ out.WriteRune(r)
width += cw
continue
}
- out += string(r)
+ out.WriteRune(r)
width += cw
}
- return out
+ return out.String()
}
// FillLeft return string filled in left by spaces in w cells
@@ -313,7 +450,12 @@ func RuneWidth(r rune) int {
// IsAmbiguousWidth returns whether is ambiguous width or not.
func IsAmbiguousWidth(r rune) bool {
- return inTables(r, private, ambiguous)
+ return inTable(r, private) || inTable(r, ambiguous)
+}
+
+// IsCombiningWidth returns whether is combining width or not.
+func IsCombiningWidth(r rune) bool {
+ return inTable(r, combining)
}
// IsNeutralWidth returns whether is neutral width or not.
diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_table.go b/vendor/github.com/mattn/go-runewidth/runewidth_table.go
index ad025ad5..cdd003e6 100644
--- a/vendor/github.com/mattn/go-runewidth/runewidth_table.go
+++ b/vendor/github.com/mattn/go-runewidth/runewidth_table.go
@@ -5,47 +5,50 @@ package runewidth
var combining = table{
{0x0300, 0x036F}, {0x0483, 0x0489}, {0x07EB, 0x07F3},
{0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0CF3, 0x0CF3},
- {0x0D00, 0x0D01}, {0x135D, 0x135F}, {0x1A7F, 0x1A7F},
- {0x1AB0, 0x1ACE}, {0x1B6B, 0x1B73}, {0x1DC0, 0x1DFF},
+ {0x0D00, 0x0D01}, {0x135D, 0x135F}, {0x180B, 0x180D},
+ {0x180F, 0x180F}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1ADD},
+ {0x1AE0, 0x1AEB}, {0x1B6B, 0x1B73}, {0x1DC0, 0x1DFF},
{0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2DE0, 0x2DFF},
{0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D},
{0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA8E0, 0xA8F1},
- {0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, {0x10376, 0x1037A},
- {0x10EAB, 0x10EAC}, {0x10F46, 0x10F50}, {0x10F82, 0x10F85},
- {0x11300, 0x11301}, {0x1133B, 0x1133C}, {0x11366, 0x1136C},
- {0x11370, 0x11374}, {0x16AF0, 0x16AF4}, {0x1CF00, 0x1CF2D},
- {0x1CF30, 0x1CF46}, {0x1D165, 0x1D169}, {0x1D16D, 0x1D172},
- {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
- {0x1D242, 0x1D244}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018},
- {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, {0x1E026, 0x1E02A},
- {0x1E08F, 0x1E08F}, {0x1E8D0, 0x1E8D6},
+ {0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD},
+ {0x10376, 0x1037A}, {0x10EAB, 0x10EAC}, {0x10F46, 0x10F50},
+ {0x10F82, 0x10F85}, {0x11300, 0x11301}, {0x1133B, 0x1133C},
+ {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x16AF0, 0x16AF4},
+ {0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, {0x1D165, 0x1D169},
+ {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B},
+ {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1E000, 0x1E006},
+ {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024},
+ {0x1E026, 0x1E02A}, {0x1E08F, 0x1E08F}, {0x1E8D0, 0x1E8D6},
+ {0xE0100, 0xE01EF},
}
var doublewidth = table{
{0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A},
{0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3},
- {0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653},
- {0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1},
- {0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5},
- {0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA},
- {0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA},
- {0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B},
- {0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E},
- {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797},
- {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C},
- {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99},
- {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x303E},
- {0x3041, 0x3096}, {0x3099, 0x30FF}, {0x3105, 0x312F},
- {0x3131, 0x318E}, {0x3190, 0x31E3}, {0x31EF, 0x321E},
- {0x3220, 0x3247}, {0x3250, 0x4DBF}, {0x4E00, 0xA48C},
- {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3},
- {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52},
- {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60},
- {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE4}, {0x16FF0, 0x16FF1},
- {0x17000, 0x187F7}, {0x18800, 0x18CD5}, {0x18D00, 0x18D08},
- {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB}, {0x1AFFD, 0x1AFFE},
- {0x1B000, 0x1B122}, {0x1B132, 0x1B132}, {0x1B150, 0x1B152},
- {0x1B155, 0x1B155}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB},
+ {0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2630, 0x2637},
+ {0x2648, 0x2653}, {0x267F, 0x267F}, {0x268A, 0x268F},
+ {0x2693, 0x2693}, {0x26A1, 0x26A1}, {0x26AA, 0x26AB},
+ {0x26BD, 0x26BE}, {0x26C4, 0x26C5}, {0x26CE, 0x26CE},
+ {0x26D4, 0x26D4}, {0x26EA, 0x26EA}, {0x26F2, 0x26F3},
+ {0x26F5, 0x26F5}, {0x26FA, 0x26FA}, {0x26FD, 0x26FD},
+ {0x2705, 0x2705}, {0x270A, 0x270B}, {0x2728, 0x2728},
+ {0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755},
+ {0x2757, 0x2757}, {0x2795, 0x2797}, {0x27B0, 0x27B0},
+ {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C}, {0x2B50, 0x2B50},
+ {0x2B55, 0x2B55}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3},
+ {0x2F00, 0x2FD5}, {0x2FF0, 0x303E}, {0x3041, 0x3096},
+ {0x3099, 0x30FF}, {0x3105, 0x312F}, {0x3131, 0x318E},
+ {0x3190, 0x31E5}, {0x31EF, 0x321E}, {0x3220, 0x3247},
+ {0x3250, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C},
+ {0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19},
+ {0xFE30, 0xFE52}, {0xFE54, 0xFE66}, {0xFE68, 0xFE6B},
+ {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE4},
+ {0x16FF0, 0x16FF6}, {0x17000, 0x18CD5}, {0x18CFF, 0x18D1E},
+ {0x18D80, 0x18DF2}, {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB},
+ {0x1AFFD, 0x1AFFE}, {0x1B000, 0x1B122}, {0x1B132, 0x1B132},
+ {0x1B150, 0x1B152}, {0x1B155, 0x1B155}, {0x1B164, 0x1B167},
+ {0x1B170, 0x1B2FB}, {0x1D300, 0x1D356}, {0x1D360, 0x1D376},
{0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E},
{0x1F191, 0x1F19A}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23B},
{0x1F240, 0x1F248}, {0x1F250, 0x1F251}, {0x1F260, 0x1F265},
@@ -56,12 +59,12 @@ var doublewidth = table{
{0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, {0x1F57A, 0x1F57A},
{0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4}, {0x1F5FB, 0x1F64F},
{0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D2},
- {0x1F6D5, 0x1F6D7}, {0x1F6DC, 0x1F6DF}, {0x1F6EB, 0x1F6EC},
+ {0x1F6D5, 0x1F6D8}, {0x1F6DC, 0x1F6DF}, {0x1F6EB, 0x1F6EC},
{0x1F6F4, 0x1F6FC}, {0x1F7E0, 0x1F7EB}, {0x1F7F0, 0x1F7F0},
{0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1F9FF},
- {0x1FA70, 0x1FA7C}, {0x1FA80, 0x1FA88}, {0x1FA90, 0x1FABD},
- {0x1FABF, 0x1FAC5}, {0x1FACE, 0x1FADB}, {0x1FAE0, 0x1FAE8},
- {0x1FAF0, 0x1FAF8}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
+ {0x1FA70, 0x1FA7C}, {0x1FA80, 0x1FA8A}, {0x1FA8E, 0x1FAC6},
+ {0x1FAC8, 0x1FAC8}, {0x1FACD, 0x1FADC}, {0x1FADF, 0x1FAEA},
+ {0x1FAEF, 0x1FAF8}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
}
var ambiguous = table{
@@ -121,10 +124,9 @@ var ambiguous = table{
{0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC},
{0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F},
{0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF},
- {0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A},
- {0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D},
- {0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF},
- {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD},
+ {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A}, {0x1F110, 0x1F12D},
+ {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, {0x1F18F, 0x1F190},
+ {0x1F19B, 0x1F1AC}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD},
}
var narrow = table{
{0x0020, 0x007E}, {0x00A2, 0x00A3}, {0x00A5, 0x00A6},
@@ -159,115 +161,116 @@ var neutral = table{
{0x0600, 0x070D}, {0x070F, 0x074A}, {0x074D, 0x07B1},
{0x07C0, 0x07FA}, {0x07FD, 0x082D}, {0x0830, 0x083E},
{0x0840, 0x085B}, {0x085E, 0x085E}, {0x0860, 0x086A},
- {0x0870, 0x088E}, {0x0890, 0x0891}, {0x0898, 0x0983},
- {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8},
- {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9},
- {0x09BC, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CE},
- {0x09D7, 0x09D7}, {0x09DC, 0x09DD}, {0x09DF, 0x09E3},
- {0x09E6, 0x09FE}, {0x0A01, 0x0A03}, {0x0A05, 0x0A0A},
- {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30},
- {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39},
- {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, {0x0A47, 0x0A48},
- {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, {0x0A59, 0x0A5C},
- {0x0A5E, 0x0A5E}, {0x0A66, 0x0A76}, {0x0A81, 0x0A83},
- {0x0A85, 0x0A8D}, {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8},
- {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9},
- {0x0ABC, 0x0AC5}, {0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD},
- {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE3}, {0x0AE6, 0x0AF1},
- {0x0AF9, 0x0AFF}, {0x0B01, 0x0B03}, {0x0B05, 0x0B0C},
- {0x0B0F, 0x0B10}, {0x0B13, 0x0B28}, {0x0B2A, 0x0B30},
- {0x0B32, 0x0B33}, {0x0B35, 0x0B39}, {0x0B3C, 0x0B44},
- {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D}, {0x0B55, 0x0B57},
- {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B63}, {0x0B66, 0x0B77},
- {0x0B82, 0x0B83}, {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90},
- {0x0B92, 0x0B95}, {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C},
- {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA},
- {0x0BAE, 0x0BB9}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8},
- {0x0BCA, 0x0BCD}, {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7},
- {0x0BE6, 0x0BFA}, {0x0C00, 0x0C0C}, {0x0C0E, 0x0C10},
- {0x0C12, 0x0C28}, {0x0C2A, 0x0C39}, {0x0C3C, 0x0C44},
- {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56},
- {0x0C58, 0x0C5A}, {0x0C5D, 0x0C5D}, {0x0C60, 0x0C63},
- {0x0C66, 0x0C6F}, {0x0C77, 0x0C8C}, {0x0C8E, 0x0C90},
- {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9},
- {0x0CBC, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD},
- {0x0CD5, 0x0CD6}, {0x0CDD, 0x0CDE}, {0x0CE0, 0x0CE3},
- {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF3}, {0x0D00, 0x0D0C},
- {0x0D0E, 0x0D10}, {0x0D12, 0x0D44}, {0x0D46, 0x0D48},
- {0x0D4A, 0x0D4F}, {0x0D54, 0x0D63}, {0x0D66, 0x0D7F},
- {0x0D81, 0x0D83}, {0x0D85, 0x0D96}, {0x0D9A, 0x0DB1},
- {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, {0x0DC0, 0x0DC6},
- {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, {0x0DD6, 0x0DD6},
- {0x0DD8, 0x0DDF}, {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF4},
- {0x0E01, 0x0E3A}, {0x0E3F, 0x0E5B}, {0x0E81, 0x0E82},
- {0x0E84, 0x0E84}, {0x0E86, 0x0E8A}, {0x0E8C, 0x0EA3},
- {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EBD}, {0x0EC0, 0x0EC4},
- {0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECE}, {0x0ED0, 0x0ED9},
- {0x0EDC, 0x0EDF}, {0x0F00, 0x0F47}, {0x0F49, 0x0F6C},
- {0x0F71, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC},
- {0x0FCE, 0x0FDA}, {0x1000, 0x10C5}, {0x10C7, 0x10C7},
- {0x10CD, 0x10CD}, {0x10D0, 0x10FF}, {0x1160, 0x1248},
- {0x124A, 0x124D}, {0x1250, 0x1256}, {0x1258, 0x1258},
- {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D},
- {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE},
- {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, {0x12C8, 0x12D6},
- {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A},
- {0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5},
- {0x13F8, 0x13FD}, {0x1400, 0x169C}, {0x16A0, 0x16F8},
- {0x1700, 0x1715}, {0x171F, 0x1736}, {0x1740, 0x1753},
- {0x1760, 0x176C}, {0x176E, 0x1770}, {0x1772, 0x1773},
- {0x1780, 0x17DD}, {0x17E0, 0x17E9}, {0x17F0, 0x17F9},
- {0x1800, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA},
- {0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1920, 0x192B},
- {0x1930, 0x193B}, {0x1940, 0x1940}, {0x1944, 0x196D},
- {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9},
- {0x19D0, 0x19DA}, {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E},
- {0x1A60, 0x1A7C}, {0x1A7F, 0x1A89}, {0x1A90, 0x1A99},
- {0x1AA0, 0x1AAD}, {0x1AB0, 0x1ACE}, {0x1B00, 0x1B4C},
- {0x1B50, 0x1B7E}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37},
- {0x1C3B, 0x1C49}, {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA},
- {0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA}, {0x1D00, 0x1F15},
- {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D},
- {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B},
- {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4},
- {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3}, {0x1FD6, 0x1FDB},
- {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFE},
- {0x2000, 0x200F}, {0x2011, 0x2012}, {0x2017, 0x2017},
- {0x201A, 0x201B}, {0x201E, 0x201F}, {0x2023, 0x2023},
- {0x2028, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034},
- {0x2036, 0x203A}, {0x203C, 0x203D}, {0x203F, 0x2064},
- {0x2066, 0x2071}, {0x2075, 0x207E}, {0x2080, 0x2080},
- {0x2085, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8},
- {0x20AA, 0x20AB}, {0x20AD, 0x20C0}, {0x20D0, 0x20F0},
- {0x2100, 0x2102}, {0x2104, 0x2104}, {0x2106, 0x2108},
- {0x210A, 0x2112}, {0x2114, 0x2115}, {0x2117, 0x2120},
- {0x2123, 0x2125}, {0x2127, 0x212A}, {0x212C, 0x2152},
- {0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F},
- {0x217A, 0x2188}, {0x218A, 0x218B}, {0x219A, 0x21B7},
- {0x21BA, 0x21D1}, {0x21D3, 0x21D3}, {0x21D5, 0x21E6},
- {0x21E8, 0x21FF}, {0x2201, 0x2201}, {0x2204, 0x2206},
- {0x2209, 0x220A}, {0x220C, 0x220E}, {0x2210, 0x2210},
- {0x2212, 0x2214}, {0x2216, 0x2219}, {0x221B, 0x221C},
- {0x2221, 0x2222}, {0x2224, 0x2224}, {0x2226, 0x2226},
- {0x222D, 0x222D}, {0x222F, 0x2233}, {0x2238, 0x223B},
- {0x223E, 0x2247}, {0x2249, 0x224B}, {0x224D, 0x2251},
- {0x2253, 0x225F}, {0x2262, 0x2263}, {0x2268, 0x2269},
- {0x226C, 0x226D}, {0x2270, 0x2281}, {0x2284, 0x2285},
- {0x2288, 0x2294}, {0x2296, 0x2298}, {0x229A, 0x22A4},
- {0x22A6, 0x22BE}, {0x22C0, 0x2311}, {0x2313, 0x2319},
- {0x231C, 0x2328}, {0x232B, 0x23E8}, {0x23ED, 0x23EF},
- {0x23F1, 0x23F2}, {0x23F4, 0x2426}, {0x2440, 0x244A},
- {0x24EA, 0x24EA}, {0x254C, 0x254F}, {0x2574, 0x257F},
- {0x2590, 0x2591}, {0x2596, 0x259F}, {0x25A2, 0x25A2},
- {0x25AA, 0x25B1}, {0x25B4, 0x25B5}, {0x25B8, 0x25BB},
- {0x25BE, 0x25BF}, {0x25C2, 0x25C5}, {0x25C9, 0x25CA},
- {0x25CC, 0x25CD}, {0x25D2, 0x25E1}, {0x25E6, 0x25EE},
- {0x25F0, 0x25FC}, {0x25FF, 0x2604}, {0x2607, 0x2608},
- {0x260A, 0x260D}, {0x2610, 0x2613}, {0x2616, 0x261B},
- {0x261D, 0x261D}, {0x261F, 0x263F}, {0x2641, 0x2641},
- {0x2643, 0x2647}, {0x2654, 0x265F}, {0x2662, 0x2662},
- {0x2666, 0x2666}, {0x266B, 0x266B}, {0x266E, 0x266E},
- {0x2670, 0x267E}, {0x2680, 0x2692}, {0x2694, 0x269D},
+ {0x0870, 0x0891}, {0x0897, 0x0983}, {0x0985, 0x098C},
+ {0x098F, 0x0990}, {0x0993, 0x09A8}, {0x09AA, 0x09B0},
+ {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, {0x09BC, 0x09C4},
+ {0x09C7, 0x09C8}, {0x09CB, 0x09CE}, {0x09D7, 0x09D7},
+ {0x09DC, 0x09DD}, {0x09DF, 0x09E3}, {0x09E6, 0x09FE},
+ {0x0A01, 0x0A03}, {0x0A05, 0x0A0A}, {0x0A0F, 0x0A10},
+ {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, {0x0A32, 0x0A33},
+ {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, {0x0A3C, 0x0A3C},
+ {0x0A3E, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
+ {0x0A51, 0x0A51}, {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E},
+ {0x0A66, 0x0A76}, {0x0A81, 0x0A83}, {0x0A85, 0x0A8D},
+ {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0},
+ {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABC, 0x0AC5},
+ {0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD}, {0x0AD0, 0x0AD0},
+ {0x0AE0, 0x0AE3}, {0x0AE6, 0x0AF1}, {0x0AF9, 0x0AFF},
+ {0x0B01, 0x0B03}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10},
+ {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33},
+ {0x0B35, 0x0B39}, {0x0B3C, 0x0B44}, {0x0B47, 0x0B48},
+ {0x0B4B, 0x0B4D}, {0x0B55, 0x0B57}, {0x0B5C, 0x0B5D},
+ {0x0B5F, 0x0B63}, {0x0B66, 0x0B77}, {0x0B82, 0x0B83},
+ {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, {0x0B92, 0x0B95},
+ {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F},
+ {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9},
+ {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCD},
+ {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BFA},
+ {0x0C00, 0x0C0C}, {0x0C0E, 0x0C10}, {0x0C12, 0x0C28},
+ {0x0C2A, 0x0C39}, {0x0C3C, 0x0C44}, {0x0C46, 0x0C48},
+ {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0C58, 0x0C5A},
+ {0x0C5C, 0x0C5D}, {0x0C60, 0x0C63}, {0x0C66, 0x0C6F},
+ {0x0C77, 0x0C8C}, {0x0C8E, 0x0C90}, {0x0C92, 0x0CA8},
+ {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9}, {0x0CBC, 0x0CC4},
+ {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6},
+ {0x0CDC, 0x0CDE}, {0x0CE0, 0x0CE3}, {0x0CE6, 0x0CEF},
+ {0x0CF1, 0x0CF3}, {0x0D00, 0x0D0C}, {0x0D0E, 0x0D10},
+ {0x0D12, 0x0D44}, {0x0D46, 0x0D48}, {0x0D4A, 0x0D4F},
+ {0x0D54, 0x0D63}, {0x0D66, 0x0D7F}, {0x0D81, 0x0D83},
+ {0x0D85, 0x0D96}, {0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB},
+ {0x0DBD, 0x0DBD}, {0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA},
+ {0x0DCF, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF},
+ {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF4}, {0x0E01, 0x0E3A},
+ {0x0E3F, 0x0E5B}, {0x0E81, 0x0E82}, {0x0E84, 0x0E84},
+ {0x0E86, 0x0E8A}, {0x0E8C, 0x0EA3}, {0x0EA5, 0x0EA5},
+ {0x0EA7, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0EC6, 0x0EC6},
+ {0x0EC8, 0x0ECE}, {0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF},
+ {0x0F00, 0x0F47}, {0x0F49, 0x0F6C}, {0x0F71, 0x0F97},
+ {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC}, {0x0FCE, 0x0FDA},
+ {0x1000, 0x10C5}, {0x10C7, 0x10C7}, {0x10CD, 0x10CD},
+ {0x10D0, 0x10FF}, {0x1160, 0x1248}, {0x124A, 0x124D},
+ {0x1250, 0x1256}, {0x1258, 0x1258}, {0x125A, 0x125D},
+ {0x1260, 0x1288}, {0x128A, 0x128D}, {0x1290, 0x12B0},
+ {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, {0x12C0, 0x12C0},
+ {0x12C2, 0x12C5}, {0x12C8, 0x12D6}, {0x12D8, 0x1310},
+ {0x1312, 0x1315}, {0x1318, 0x135A}, {0x135D, 0x137C},
+ {0x1380, 0x1399}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD},
+ {0x1400, 0x169C}, {0x16A0, 0x16F8}, {0x1700, 0x1715},
+ {0x171F, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176C},
+ {0x176E, 0x1770}, {0x1772, 0x1773}, {0x1780, 0x17DD},
+ {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x180A},
+ {0x180E, 0x180E}, {0x1810, 0x1819}, {0x1820, 0x1878},
+ {0x1880, 0x18AA}, {0x18B0, 0x18F5}, {0x1900, 0x191E},
+ {0x1920, 0x192B}, {0x1930, 0x193B}, {0x1940, 0x1940},
+ {0x1944, 0x196D}, {0x1970, 0x1974}, {0x1980, 0x19AB},
+ {0x19B0, 0x19C9}, {0x19D0, 0x19DA}, {0x19DE, 0x1A1B},
+ {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A89},
+ {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD}, {0x1AB0, 0x1ADD},
+ {0x1AE0, 0x1AEB}, {0x1B00, 0x1B4C}, {0x1B4E, 0x1BF3},
+ {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49}, {0x1C4D, 0x1C8A},
+ {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA},
+ {0x1D00, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45},
+ {0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F59, 0x1F59},
+ {0x1F5B, 0x1F5B}, {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D},
+ {0x1F80, 0x1FB4}, {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3},
+ {0x1FD6, 0x1FDB}, {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4},
+ {0x1FF6, 0x1FFE}, {0x2000, 0x200F}, {0x2011, 0x2012},
+ {0x2017, 0x2017}, {0x201A, 0x201B}, {0x201E, 0x201F},
+ {0x2023, 0x2023}, {0x2028, 0x202F}, {0x2031, 0x2031},
+ {0x2034, 0x2034}, {0x2036, 0x203A}, {0x203C, 0x203D},
+ {0x203F, 0x2064}, {0x2066, 0x2071}, {0x2075, 0x207E},
+ {0x2080, 0x2080}, {0x2085, 0x208E}, {0x2090, 0x209C},
+ {0x20A0, 0x20A8}, {0x20AA, 0x20AB}, {0x20AD, 0x20C1},
+ {0x20D0, 0x20F0}, {0x2100, 0x2102}, {0x2104, 0x2104},
+ {0x2106, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2115},
+ {0x2117, 0x2120}, {0x2123, 0x2125}, {0x2127, 0x212A},
+ {0x212C, 0x2152}, {0x2155, 0x215A}, {0x215F, 0x215F},
+ {0x216C, 0x216F}, {0x217A, 0x2188}, {0x218A, 0x218B},
+ {0x219A, 0x21B7}, {0x21BA, 0x21D1}, {0x21D3, 0x21D3},
+ {0x21D5, 0x21E6}, {0x21E8, 0x21FF}, {0x2201, 0x2201},
+ {0x2204, 0x2206}, {0x2209, 0x220A}, {0x220C, 0x220E},
+ {0x2210, 0x2210}, {0x2212, 0x2214}, {0x2216, 0x2219},
+ {0x221B, 0x221C}, {0x2221, 0x2222}, {0x2224, 0x2224},
+ {0x2226, 0x2226}, {0x222D, 0x222D}, {0x222F, 0x2233},
+ {0x2238, 0x223B}, {0x223E, 0x2247}, {0x2249, 0x224B},
+ {0x224D, 0x2251}, {0x2253, 0x225F}, {0x2262, 0x2263},
+ {0x2268, 0x2269}, {0x226C, 0x226D}, {0x2270, 0x2281},
+ {0x2284, 0x2285}, {0x2288, 0x2294}, {0x2296, 0x2298},
+ {0x229A, 0x22A4}, {0x22A6, 0x22BE}, {0x22C0, 0x2311},
+ {0x2313, 0x2319}, {0x231C, 0x2328}, {0x232B, 0x23E8},
+ {0x23ED, 0x23EF}, {0x23F1, 0x23F2}, {0x23F4, 0x2429},
+ {0x2440, 0x244A}, {0x24EA, 0x24EA}, {0x254C, 0x254F},
+ {0x2574, 0x257F}, {0x2590, 0x2591}, {0x2596, 0x259F},
+ {0x25A2, 0x25A2}, {0x25AA, 0x25B1}, {0x25B4, 0x25B5},
+ {0x25B8, 0x25BB}, {0x25BE, 0x25BF}, {0x25C2, 0x25C5},
+ {0x25C9, 0x25CA}, {0x25CC, 0x25CD}, {0x25D2, 0x25E1},
+ {0x25E6, 0x25EE}, {0x25F0, 0x25FC}, {0x25FF, 0x2604},
+ {0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613},
+ {0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x262F},
+ {0x2638, 0x263F}, {0x2641, 0x2641}, {0x2643, 0x2647},
+ {0x2654, 0x265F}, {0x2662, 0x2662}, {0x2666, 0x2666},
+ {0x266B, 0x266B}, {0x266E, 0x266E}, {0x2670, 0x267E},
+ {0x2680, 0x2689}, {0x2690, 0x2692}, {0x2694, 0x269D},
{0x26A0, 0x26A0}, {0x26A2, 0x26A9}, {0x26AC, 0x26BC},
{0x26C0, 0x26C3}, {0x26E2, 0x26E2}, {0x26E4, 0x26E7},
{0x2700, 0x2704}, {0x2706, 0x2709}, {0x270C, 0x2727},
@@ -276,175 +279,210 @@ var neutral = table{
{0x2780, 0x2794}, {0x2798, 0x27AF}, {0x27B1, 0x27BE},
{0x27C0, 0x27E5}, {0x27EE, 0x2984}, {0x2987, 0x2B1A},
{0x2B1D, 0x2B4F}, {0x2B51, 0x2B54}, {0x2B5A, 0x2B73},
- {0x2B76, 0x2B95}, {0x2B97, 0x2CF3}, {0x2CF9, 0x2D25},
- {0x2D27, 0x2D27}, {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67},
- {0x2D6F, 0x2D70}, {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6},
- {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE},
- {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6},
- {0x2DD8, 0x2DDE}, {0x2DE0, 0x2E5D}, {0x303F, 0x303F},
- {0x4DC0, 0x4DFF}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7},
- {0xA700, 0xA7CA}, {0xA7D0, 0xA7D1}, {0xA7D3, 0xA7D3},
- {0xA7D5, 0xA7D9}, {0xA7F2, 0xA82C}, {0xA830, 0xA839},
- {0xA840, 0xA877}, {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9},
- {0xA8E0, 0xA953}, {0xA95F, 0xA95F}, {0xA980, 0xA9CD},
- {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36},
- {0xAA40, 0xAA4D}, {0xAA50, 0xAA59}, {0xAA5C, 0xAAC2},
- {0xAADB, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E},
- {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E},
- {0xAB30, 0xAB6B}, {0xAB70, 0xABED}, {0xABF0, 0xABF9},
- {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDFFF},
- {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFB1D, 0xFB36},
- {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41},
- {0xFB43, 0xFB44}, {0xFB46, 0xFBC2}, {0xFBD3, 0xFD8F},
- {0xFD92, 0xFDC7}, {0xFDCF, 0xFDCF}, {0xFDF0, 0xFDFF},
- {0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC},
- {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC}, {0x10000, 0x1000B},
- {0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003C, 0x1003D},
- {0x1003F, 0x1004D}, {0x10050, 0x1005D}, {0x10080, 0x100FA},
- {0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018E},
- {0x10190, 0x1019C}, {0x101A0, 0x101A0}, {0x101D0, 0x101FD},
- {0x10280, 0x1029C}, {0x102A0, 0x102D0}, {0x102E0, 0x102FB},
- {0x10300, 0x10323}, {0x1032D, 0x1034A}, {0x10350, 0x1037A},
- {0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5},
- {0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3},
- {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563},
- {0x1056F, 0x1057A}, {0x1057C, 0x1058A}, {0x1058C, 0x10592},
- {0x10594, 0x10595}, {0x10597, 0x105A1}, {0x105A3, 0x105B1},
- {0x105B3, 0x105B9}, {0x105BB, 0x105BC}, {0x10600, 0x10736},
- {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10780, 0x10785},
- {0x10787, 0x107B0}, {0x107B2, 0x107BA}, {0x10800, 0x10805},
- {0x10808, 0x10808}, {0x1080A, 0x10835}, {0x10837, 0x10838},
- {0x1083C, 0x1083C}, {0x1083F, 0x10855}, {0x10857, 0x1089E},
- {0x108A7, 0x108AF}, {0x108E0, 0x108F2}, {0x108F4, 0x108F5},
- {0x108FB, 0x1091B}, {0x1091F, 0x10939}, {0x1093F, 0x1093F},
- {0x10980, 0x109B7}, {0x109BC, 0x109CF}, {0x109D2, 0x10A03},
- {0x10A05, 0x10A06}, {0x10A0C, 0x10A13}, {0x10A15, 0x10A17},
- {0x10A19, 0x10A35}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48},
- {0x10A50, 0x10A58}, {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6},
- {0x10AEB, 0x10AF6}, {0x10B00, 0x10B35}, {0x10B39, 0x10B55},
- {0x10B58, 0x10B72}, {0x10B78, 0x10B91}, {0x10B99, 0x10B9C},
- {0x10BA9, 0x10BAF}, {0x10C00, 0x10C48}, {0x10C80, 0x10CB2},
- {0x10CC0, 0x10CF2}, {0x10CFA, 0x10D27}, {0x10D30, 0x10D39},
- {0x10E60, 0x10E7E}, {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD},
- {0x10EB0, 0x10EB1}, {0x10EFD, 0x10F27}, {0x10F30, 0x10F59},
- {0x10F70, 0x10F89}, {0x10FB0, 0x10FCB}, {0x10FE0, 0x10FF6},
- {0x11000, 0x1104D}, {0x11052, 0x11075}, {0x1107F, 0x110C2},
- {0x110CD, 0x110CD}, {0x110D0, 0x110E8}, {0x110F0, 0x110F9},
- {0x11100, 0x11134}, {0x11136, 0x11147}, {0x11150, 0x11176},
- {0x11180, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211},
- {0x11213, 0x11241}, {0x11280, 0x11286}, {0x11288, 0x11288},
- {0x1128A, 0x1128D}, {0x1128F, 0x1129D}, {0x1129F, 0x112A9},
- {0x112B0, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11303},
- {0x11305, 0x1130C}, {0x1130F, 0x11310}, {0x11313, 0x11328},
- {0x1132A, 0x11330}, {0x11332, 0x11333}, {0x11335, 0x11339},
- {0x1133B, 0x11344}, {0x11347, 0x11348}, {0x1134B, 0x1134D},
- {0x11350, 0x11350}, {0x11357, 0x11357}, {0x1135D, 0x11363},
- {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x1145B},
+ {0x2B76, 0x2CF3}, {0x2CF9, 0x2D25}, {0x2D27, 0x2D27},
+ {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D70},
+ {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE},
+ {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6},
+ {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE},
+ {0x2DE0, 0x2E5D}, {0x303F, 0x303F}, {0xA4D0, 0xA62B},
+ {0xA640, 0xA6F7}, {0xA700, 0xA7DC}, {0xA7F1, 0xA82C},
+ {0xA830, 0xA839}, {0xA840, 0xA877}, {0xA880, 0xA8C5},
+ {0xA8CE, 0xA8D9}, {0xA8E0, 0xA953}, {0xA95F, 0xA95F},
+ {0xA980, 0xA9CD}, {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE},
+ {0xAA00, 0xAA36}, {0xAA40, 0xAA4D}, {0xAA50, 0xAA59},
+ {0xAA5C, 0xAAC2}, {0xAADB, 0xAAF6}, {0xAB01, 0xAB06},
+ {0xAB09, 0xAB0E}, {0xAB11, 0xAB16}, {0xAB20, 0xAB26},
+ {0xAB28, 0xAB2E}, {0xAB30, 0xAB6B}, {0xAB70, 0xABED},
+ {0xABF0, 0xABF9}, {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB},
+ {0xD800, 0xDFFF}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17},
+ {0xFB1D, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E},
+ {0xFB40, 0xFB41}, {0xFB43, 0xFB44}, {0xFB46, 0xFDCF},
+ {0xFDF0, 0xFDFF}, {0xFE20, 0xFE2F}, {0xFE70, 0xFE74},
+ {0xFE76, 0xFEFC}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC},
+ {0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A},
+ {0x1003C, 0x1003D}, {0x1003F, 0x1004D}, {0x10050, 0x1005D},
+ {0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133},
+ {0x10137, 0x1018E}, {0x10190, 0x1019C}, {0x101A0, 0x101A0},
+ {0x101D0, 0x101FD}, {0x10280, 0x1029C}, {0x102A0, 0x102D0},
+ {0x102E0, 0x102FB}, {0x10300, 0x10323}, {0x1032D, 0x1034A},
+ {0x10350, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x103C3},
+ {0x103C8, 0x103D5}, {0x10400, 0x1049D}, {0x104A0, 0x104A9},
+ {0x104B0, 0x104D3}, {0x104D8, 0x104FB}, {0x10500, 0x10527},
+ {0x10530, 0x10563}, {0x1056F, 0x1057A}, {0x1057C, 0x1058A},
+ {0x1058C, 0x10592}, {0x10594, 0x10595}, {0x10597, 0x105A1},
+ {0x105A3, 0x105B1}, {0x105B3, 0x105B9}, {0x105BB, 0x105BC},
+ {0x105C0, 0x105F3}, {0x10600, 0x10736}, {0x10740, 0x10755},
+ {0x10760, 0x10767}, {0x10780, 0x10785}, {0x10787, 0x107B0},
+ {0x107B2, 0x107BA}, {0x10800, 0x10805}, {0x10808, 0x10808},
+ {0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C},
+ {0x1083F, 0x10855}, {0x10857, 0x1089E}, {0x108A7, 0x108AF},
+ {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x1091B},
+ {0x1091F, 0x10939}, {0x1093F, 0x10959}, {0x10980, 0x109B7},
+ {0x109BC, 0x109CF}, {0x109D2, 0x10A03}, {0x10A05, 0x10A06},
+ {0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A35},
+ {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48}, {0x10A50, 0x10A58},
+ {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, {0x10AEB, 0x10AF6},
+ {0x10B00, 0x10B35}, {0x10B39, 0x10B55}, {0x10B58, 0x10B72},
+ {0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF},
+ {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2},
+ {0x10CFA, 0x10D27}, {0x10D30, 0x10D39}, {0x10D40, 0x10D65},
+ {0x10D69, 0x10D85}, {0x10D8E, 0x10D8F}, {0x10E60, 0x10E7E},
+ {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD}, {0x10EB0, 0x10EB1},
+ {0x10EC2, 0x10EC7}, {0x10ED0, 0x10ED8}, {0x10EFA, 0x10F27},
+ {0x10F30, 0x10F59}, {0x10F70, 0x10F89}, {0x10FB0, 0x10FCB},
+ {0x10FE0, 0x10FF6}, {0x11000, 0x1104D}, {0x11052, 0x11075},
+ {0x1107F, 0x110C2}, {0x110CD, 0x110CD}, {0x110D0, 0x110E8},
+ {0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11147},
+ {0x11150, 0x11176}, {0x11180, 0x111DF}, {0x111E1, 0x111F4},
+ {0x11200, 0x11211}, {0x11213, 0x11241}, {0x11280, 0x11286},
+ {0x11288, 0x11288}, {0x1128A, 0x1128D}, {0x1128F, 0x1129D},
+ {0x1129F, 0x112A9}, {0x112B0, 0x112EA}, {0x112F0, 0x112F9},
+ {0x11300, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310},
+ {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333},
+ {0x11335, 0x11339}, {0x1133B, 0x11344}, {0x11347, 0x11348},
+ {0x1134B, 0x1134D}, {0x11350, 0x11350}, {0x11357, 0x11357},
+ {0x1135D, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374},
+ {0x11380, 0x11389}, {0x1138B, 0x1138B}, {0x1138E, 0x1138E},
+ {0x11390, 0x113B5}, {0x113B7, 0x113C0}, {0x113C2, 0x113C2},
+ {0x113C5, 0x113C5}, {0x113C7, 0x113CA}, {0x113CC, 0x113D5},
+ {0x113D7, 0x113D8}, {0x113E1, 0x113E2}, {0x11400, 0x1145B},
{0x1145D, 0x11461}, {0x11480, 0x114C7}, {0x114D0, 0x114D9},
{0x11580, 0x115B5}, {0x115B8, 0x115DD}, {0x11600, 0x11644},
{0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B9},
- {0x116C0, 0x116C9}, {0x11700, 0x1171A}, {0x1171D, 0x1172B},
- {0x11730, 0x11746}, {0x11800, 0x1183B}, {0x118A0, 0x118F2},
- {0x118FF, 0x11906}, {0x11909, 0x11909}, {0x1190C, 0x11913},
- {0x11915, 0x11916}, {0x11918, 0x11935}, {0x11937, 0x11938},
- {0x1193B, 0x11946}, {0x11950, 0x11959}, {0x119A0, 0x119A7},
- {0x119AA, 0x119D7}, {0x119DA, 0x119E4}, {0x11A00, 0x11A47},
- {0x11A50, 0x11AA2}, {0x11AB0, 0x11AF8}, {0x11B00, 0x11B09},
- {0x11C00, 0x11C08}, {0x11C0A, 0x11C36}, {0x11C38, 0x11C45},
- {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F}, {0x11C92, 0x11CA7},
- {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06}, {0x11D08, 0x11D09},
- {0x11D0B, 0x11D36}, {0x11D3A, 0x11D3A}, {0x11D3C, 0x11D3D},
- {0x11D3F, 0x11D47}, {0x11D50, 0x11D59}, {0x11D60, 0x11D65},
- {0x11D67, 0x11D68}, {0x11D6A, 0x11D8E}, {0x11D90, 0x11D91},
- {0x11D93, 0x11D98}, {0x11DA0, 0x11DA9}, {0x11EE0, 0x11EF8},
- {0x11F00, 0x11F10}, {0x11F12, 0x11F3A}, {0x11F3E, 0x11F59},
+ {0x116C0, 0x116C9}, {0x116D0, 0x116E3}, {0x11700, 0x1171A},
+ {0x1171D, 0x1172B}, {0x11730, 0x11746}, {0x11800, 0x1183B},
+ {0x118A0, 0x118F2}, {0x118FF, 0x11906}, {0x11909, 0x11909},
+ {0x1190C, 0x11913}, {0x11915, 0x11916}, {0x11918, 0x11935},
+ {0x11937, 0x11938}, {0x1193B, 0x11946}, {0x11950, 0x11959},
+ {0x119A0, 0x119A7}, {0x119AA, 0x119D7}, {0x119DA, 0x119E4},
+ {0x11A00, 0x11A47}, {0x11A50, 0x11AA2}, {0x11AB0, 0x11AF8},
+ {0x11B00, 0x11B09}, {0x11B60, 0x11B67}, {0x11BC0, 0x11BE1},
+ {0x11BF0, 0x11BF9}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C36},
+ {0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F},
+ {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06},
+ {0x11D08, 0x11D09}, {0x11D0B, 0x11D36}, {0x11D3A, 0x11D3A},
+ {0x11D3C, 0x11D3D}, {0x11D3F, 0x11D47}, {0x11D50, 0x11D59},
+ {0x11D60, 0x11D65}, {0x11D67, 0x11D68}, {0x11D6A, 0x11D8E},
+ {0x11D90, 0x11D91}, {0x11D93, 0x11D98}, {0x11DA0, 0x11DA9},
+ {0x11DB0, 0x11DDB}, {0x11DE0, 0x11DE9}, {0x11EE0, 0x11EF8},
+ {0x11F00, 0x11F10}, {0x11F12, 0x11F3A}, {0x11F3E, 0x11F5A},
{0x11FB0, 0x11FB0}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399},
{0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543},
- {0x12F90, 0x12FF2}, {0x13000, 0x13455}, {0x14400, 0x14646},
- {0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A60, 0x16A69},
- {0x16A6E, 0x16ABE}, {0x16AC0, 0x16AC9}, {0x16AD0, 0x16AED},
- {0x16AF0, 0x16AF5}, {0x16B00, 0x16B45}, {0x16B50, 0x16B59},
- {0x16B5B, 0x16B61}, {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F},
- {0x16E40, 0x16E9A}, {0x16F00, 0x16F4A}, {0x16F4F, 0x16F87},
- {0x16F8F, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C},
- {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3},
+ {0x12F90, 0x12FF2}, {0x13000, 0x13455}, {0x13460, 0x143FA},
+ {0x14400, 0x14646}, {0x16100, 0x16139}, {0x16800, 0x16A38},
+ {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, {0x16A6E, 0x16ABE},
+ {0x16AC0, 0x16AC9}, {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF5},
+ {0x16B00, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61},
+ {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16D40, 0x16D79},
+ {0x16E40, 0x16E9A}, {0x16EA0, 0x16EB8}, {0x16EBB, 0x16ED3},
+ {0x16F00, 0x16F4A}, {0x16F4F, 0x16F87}, {0x16F8F, 0x16F9F},
+ {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88},
+ {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3}, {0x1CC00, 0x1CCFC},
+ {0x1CD00, 0x1CEB3}, {0x1CEBA, 0x1CED0}, {0x1CEE0, 0x1CEF0},
{0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, {0x1CF50, 0x1CFC3},
{0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D1EA},
{0x1D200, 0x1D245}, {0x1D2C0, 0x1D2D3}, {0x1D2E0, 0x1D2F3},
- {0x1D300, 0x1D356}, {0x1D360, 0x1D378}, {0x1D400, 0x1D454},
- {0x1D456, 0x1D49C}, {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2},
- {0x1D4A5, 0x1D4A6}, {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9},
- {0x1D4BB, 0x1D4BB}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505},
- {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C},
- {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544},
- {0x1D546, 0x1D546}, {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5},
- {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B}, {0x1DA9B, 0x1DA9F},
- {0x1DAA1, 0x1DAAF}, {0x1DF00, 0x1DF1E}, {0x1DF25, 0x1DF2A},
- {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021},
- {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E030, 0x1E06D},
- {0x1E08F, 0x1E08F}, {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D},
- {0x1E140, 0x1E149}, {0x1E14E, 0x1E14F}, {0x1E290, 0x1E2AE},
- {0x1E2C0, 0x1E2F9}, {0x1E2FF, 0x1E2FF}, {0x1E4D0, 0x1E4F9},
- {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB}, {0x1E7ED, 0x1E7EE},
- {0x1E7F0, 0x1E7FE}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6},
- {0x1E900, 0x1E94B}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F},
- {0x1EC71, 0x1ECB4}, {0x1ED01, 0x1ED3D}, {0x1EE00, 0x1EE03},
- {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, {0x1EE24, 0x1EE24},
- {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, {0x1EE34, 0x1EE37},
- {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, {0x1EE42, 0x1EE42},
- {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49}, {0x1EE4B, 0x1EE4B},
- {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52}, {0x1EE54, 0x1EE54},
- {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59}, {0x1EE5B, 0x1EE5B},
- {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F}, {0x1EE61, 0x1EE62},
- {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72},
- {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, {0x1EE7E, 0x1EE7E},
- {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, {0x1EEA1, 0x1EEA3},
- {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, {0x1EEF0, 0x1EEF1},
- {0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, {0x1F030, 0x1F093},
- {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CE},
- {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10F}, {0x1F12E, 0x1F12F},
- {0x1F16A, 0x1F16F}, {0x1F1AD, 0x1F1AD}, {0x1F1E6, 0x1F1FF},
- {0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D},
- {0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF},
- {0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F},
- {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A},
- {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594},
- {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F},
- {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6D3, 0x1F6D4},
- {0x1F6E0, 0x1F6EA}, {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F776},
- {0x1F77B, 0x1F7D9}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847},
+ {0x1D377, 0x1D378}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C},
+ {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6},
+ {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB},
+ {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A},
+ {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539},
+ {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D546, 0x1D546},
+ {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D7CB},
+ {0x1D7CE, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF},
+ {0x1DF00, 0x1DF1E}, {0x1DF25, 0x1DF2A}, {0x1E000, 0x1E006},
+ {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024},
+ {0x1E026, 0x1E02A}, {0x1E030, 0x1E06D}, {0x1E08F, 0x1E08F},
+ {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D}, {0x1E140, 0x1E149},
+ {0x1E14E, 0x1E14F}, {0x1E290, 0x1E2AE}, {0x1E2C0, 0x1E2F9},
+ {0x1E2FF, 0x1E2FF}, {0x1E4D0, 0x1E4F9}, {0x1E5D0, 0x1E5FA},
+ {0x1E5FF, 0x1E5FF}, {0x1E6C0, 0x1E6DE}, {0x1E6E0, 0x1E6F5},
+ {0x1E6FE, 0x1E6FF}, {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB},
+ {0x1E7ED, 0x1E7EE}, {0x1E7F0, 0x1E7FE}, {0x1E800, 0x1E8C4},
+ {0x1E8C7, 0x1E8D6}, {0x1E900, 0x1E94B}, {0x1E950, 0x1E959},
+ {0x1E95E, 0x1E95F}, {0x1EC71, 0x1ECB4}, {0x1ED01, 0x1ED3D},
+ {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22},
+ {0x1EE24, 0x1EE24}, {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32},
+ {0x1EE34, 0x1EE37}, {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B},
+ {0x1EE42, 0x1EE42}, {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49},
+ {0x1EE4B, 0x1EE4B}, {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52},
+ {0x1EE54, 0x1EE54}, {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59},
+ {0x1EE5B, 0x1EE5B}, {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F},
+ {0x1EE61, 0x1EE62}, {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A},
+ {0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C},
+ {0x1EE7E, 0x1EE7E}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B},
+ {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB},
+ {0x1EEF0, 0x1EEF1}, {0x1F000, 0x1F003}, {0x1F005, 0x1F02B},
+ {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF},
+ {0x1F0C1, 0x1F0CE}, {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10F},
+ {0x1F12E, 0x1F12F}, {0x1F16A, 0x1F16F}, {0x1F1AD, 0x1F1AD},
+ {0x1F1E6, 0x1F1FF}, {0x1F321, 0x1F32C}, {0x1F336, 0x1F336},
+ {0x1F37D, 0x1F37D}, {0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE},
+ {0x1F3D4, 0x1F3DF}, {0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7},
+ {0x1F43F, 0x1F43F}, {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE},
+ {0x1F53E, 0x1F54A}, {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579},
+ {0x1F57B, 0x1F594}, {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA},
+ {0x1F650, 0x1F67F}, {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF},
+ {0x1F6D3, 0x1F6D4}, {0x1F6E0, 0x1F6EA}, {0x1F6F0, 0x1F6F3},
+ {0x1F700, 0x1F7D9}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847},
{0x1F850, 0x1F859}, {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD},
- {0x1F8B0, 0x1F8B1}, {0x1F900, 0x1F90B}, {0x1F93B, 0x1F93B},
- {0x1F946, 0x1F946}, {0x1FA00, 0x1FA53}, {0x1FA60, 0x1FA6D},
- {0x1FB00, 0x1FB92}, {0x1FB94, 0x1FBCA}, {0x1FBF0, 0x1FBF9},
- {0xE0001, 0xE0001}, {0xE0020, 0xE007F},
+ {0x1F8B0, 0x1F8BB}, {0x1F8C0, 0x1F8C1}, {0x1F8D0, 0x1F8D8},
+ {0x1F900, 0x1F90B}, {0x1F93B, 0x1F93B}, {0x1F946, 0x1F946},
+ {0x1FA00, 0x1FA57}, {0x1FA60, 0x1FA6D}, {0x1FB00, 0x1FB92},
+ {0x1FB94, 0x1FBFA}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F},
}
var emoji = table{
{0x203C, 0x203C}, {0x2049, 0x2049}, {0x2122, 0x2122},
{0x2139, 0x2139}, {0x2194, 0x2199}, {0x21A9, 0x21AA},
- {0x231A, 0x231B}, {0x2328, 0x2328}, {0x2388, 0x2388},
- {0x23CF, 0x23CF}, {0x23E9, 0x23F3}, {0x23F8, 0x23FA},
- {0x24C2, 0x24C2}, {0x25AA, 0x25AB}, {0x25B6, 0x25B6},
- {0x25C0, 0x25C0}, {0x25FB, 0x25FE}, {0x2600, 0x2605},
- {0x2607, 0x2612}, {0x2614, 0x2685}, {0x2690, 0x2705},
- {0x2708, 0x2712}, {0x2714, 0x2714}, {0x2716, 0x2716},
- {0x271D, 0x271D}, {0x2721, 0x2721}, {0x2728, 0x2728},
- {0x2733, 0x2734}, {0x2744, 0x2744}, {0x2747, 0x2747},
- {0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755},
- {0x2757, 0x2757}, {0x2763, 0x2767}, {0x2795, 0x2797},
- {0x27A1, 0x27A1}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF},
- {0x2934, 0x2935}, {0x2B05, 0x2B07}, {0x2B1B, 0x2B1C},
- {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x3030, 0x3030},
- {0x303D, 0x303D}, {0x3297, 0x3297}, {0x3299, 0x3299},
- {0x1F000, 0x1F0FF}, {0x1F10D, 0x1F10F}, {0x1F12F, 0x1F12F},
- {0x1F16C, 0x1F171}, {0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E},
- {0x1F191, 0x1F19A}, {0x1F1AD, 0x1F1E5}, {0x1F201, 0x1F20F},
- {0x1F21A, 0x1F21A}, {0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A},
- {0x1F23C, 0x1F23F}, {0x1F249, 0x1F3FA}, {0x1F400, 0x1F53D},
- {0x1F546, 0x1F64F}, {0x1F680, 0x1F6FF}, {0x1F774, 0x1F77F},
- {0x1F7D5, 0x1F7FF}, {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F},
- {0x1F85A, 0x1F85F}, {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F8FF},
- {0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1FAFF},
+ {0x231A, 0x231B}, {0x2328, 0x2328}, {0x23CF, 0x23CF},
+ {0x23E9, 0x23F3}, {0x23F8, 0x23FA}, {0x24C2, 0x24C2},
+ {0x25AA, 0x25AB}, {0x25B6, 0x25B6}, {0x25C0, 0x25C0},
+ {0x25FB, 0x25FE}, {0x2600, 0x2604}, {0x260E, 0x260E},
+ {0x2611, 0x2611}, {0x2614, 0x2615}, {0x2618, 0x2618},
+ {0x261D, 0x261D}, {0x2620, 0x2620}, {0x2622, 0x2623},
+ {0x2626, 0x2626}, {0x262A, 0x262A}, {0x262E, 0x262F},
+ {0x2638, 0x263A}, {0x2640, 0x2640}, {0x2642, 0x2642},
+ {0x2648, 0x2653}, {0x265F, 0x2660}, {0x2663, 0x2663},
+ {0x2665, 0x2666}, {0x2668, 0x2668}, {0x267B, 0x267B},
+ {0x267E, 0x267F}, {0x2692, 0x2697}, {0x2699, 0x2699},
+ {0x269B, 0x269C}, {0x26A0, 0x26A1}, {0x26A7, 0x26A7},
+ {0x26AA, 0x26AB}, {0x26B0, 0x26B1}, {0x26BD, 0x26BE},
+ {0x26C4, 0x26C5}, {0x26C8, 0x26C8}, {0x26CE, 0x26CF},
+ {0x26D1, 0x26D1}, {0x26D3, 0x26D4}, {0x26E9, 0x26EA},
+ {0x26F0, 0x26F5}, {0x26F7, 0x26FA}, {0x26FD, 0x26FD},
+ {0x2702, 0x2702}, {0x2705, 0x2705}, {0x2708, 0x270D},
+ {0x270F, 0x270F}, {0x2712, 0x2712}, {0x2714, 0x2714},
+ {0x2716, 0x2716}, {0x271D, 0x271D}, {0x2721, 0x2721},
+ {0x2728, 0x2728}, {0x2733, 0x2734}, {0x2744, 0x2744},
+ {0x2747, 0x2747}, {0x274C, 0x274C}, {0x274E, 0x274E},
+ {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2763, 0x2764},
+ {0x2795, 0x2797}, {0x27A1, 0x27A1}, {0x27B0, 0x27B0},
+ {0x27BF, 0x27BF}, {0x2934, 0x2935}, {0x2B05, 0x2B07},
+ {0x2B1B, 0x2B1C}, {0x2B50, 0x2B50}, {0x2B55, 0x2B55},
+ {0x3030, 0x3030}, {0x303D, 0x303D}, {0x3297, 0x3297},
+ {0x3299, 0x3299}, {0x1F004, 0x1F004}, {0x1F02C, 0x1F02F},
+ {0x1F094, 0x1F09F}, {0x1F0AF, 0x1F0B0}, {0x1F0C0, 0x1F0C0},
+ {0x1F0CF, 0x1F0D0}, {0x1F0F6, 0x1F0FF}, {0x1F170, 0x1F171},
+ {0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A},
+ {0x1F1AE, 0x1F1E5}, {0x1F201, 0x1F20F}, {0x1F21A, 0x1F21A},
+ {0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A}, {0x1F23C, 0x1F23F},
+ {0x1F249, 0x1F25F}, {0x1F266, 0x1F321}, {0x1F324, 0x1F393},
+ {0x1F396, 0x1F397}, {0x1F399, 0x1F39B}, {0x1F39E, 0x1F3F0},
+ {0x1F3F3, 0x1F3F5}, {0x1F3F7, 0x1F3FA}, {0x1F400, 0x1F4FD},
+ {0x1F4FF, 0x1F53D}, {0x1F549, 0x1F54E}, {0x1F550, 0x1F567},
+ {0x1F56F, 0x1F570}, {0x1F573, 0x1F57A}, {0x1F587, 0x1F587},
+ {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590}, {0x1F595, 0x1F596},
+ {0x1F5A4, 0x1F5A5}, {0x1F5A8, 0x1F5A8}, {0x1F5B1, 0x1F5B2},
+ {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4}, {0x1F5D1, 0x1F5D3},
+ {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1}, {0x1F5E3, 0x1F5E3},
+ {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF}, {0x1F5F3, 0x1F5F3},
+ {0x1F5FA, 0x1F64F}, {0x1F680, 0x1F6C5}, {0x1F6CB, 0x1F6D2},
+ {0x1F6D5, 0x1F6E5}, {0x1F6E9, 0x1F6E9}, {0x1F6EB, 0x1F6F0},
+ {0x1F6F3, 0x1F6FF}, {0x1F7DA, 0x1F7FF}, {0x1F80C, 0x1F80F},
+ {0x1F848, 0x1F84F}, {0x1F85A, 0x1F85F}, {0x1F888, 0x1F88F},
+ {0x1F8AE, 0x1F8AF}, {0x1F8BC, 0x1F8BF}, {0x1F8C2, 0x1F8CF},
+ {0x1F8D9, 0x1F8FF}, {0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945},
+ {0x1F947, 0x1F9FF}, {0x1FA58, 0x1FA5F}, {0x1FA6E, 0x1FAFF},
{0x1FC00, 0x1FFFD},
}
diff --git a/vendor/github.com/muesli/termenv/.gitignore b/vendor/github.com/muesli/cancelreader/.gitignore
similarity index 100%
rename from vendor/github.com/muesli/termenv/.gitignore
rename to vendor/github.com/muesli/cancelreader/.gitignore
diff --git a/vendor/github.com/muesli/termenv/.golangci-soft.yml b/vendor/github.com/muesli/cancelreader/.golangci-soft.yml
similarity index 89%
rename from vendor/github.com/muesli/termenv/.golangci-soft.yml
rename to vendor/github.com/muesli/cancelreader/.golangci-soft.yml
index 84e3d41d..ef456e06 100644
--- a/vendor/github.com/muesli/termenv/.golangci-soft.yml
+++ b/vendor/github.com/muesli/cancelreader/.golangci-soft.yml
@@ -20,9 +20,10 @@ linters:
- goconst
- godot
- godox
- - mnd
+ - gomnd
- gomoddirectives
- goprintffuncname
+ - ifshort
# - lll
- misspell
- nakedret
@@ -34,10 +35,13 @@ linters:
# disable default linters, they are already enabled in .golangci.yml
disable:
+ - deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
+ - structcheck
- typecheck
- unused
+ - varcheck
diff --git a/vendor/github.com/muesli/termenv/.golangci.yml b/vendor/github.com/muesli/cancelreader/.golangci.yml
similarity index 94%
rename from vendor/github.com/muesli/termenv/.golangci.yml
rename to vendor/github.com/muesli/cancelreader/.golangci.yml
index 684d54bf..a5a91d0d 100644
--- a/vendor/github.com/muesli/termenv/.golangci.yml
+++ b/vendor/github.com/muesli/cancelreader/.golangci.yml
@@ -15,6 +15,7 @@ issues:
linters:
enable:
- bodyclose
+ - exportloopref
- goimports
- gosec
- nilerr
diff --git a/vendor/github.com/muesli/cancelreader/LICENSE b/vendor/github.com/muesli/cancelreader/LICENSE
new file mode 100644
index 00000000..4b19b92d
--- /dev/null
+++ b/vendor/github.com/muesli/cancelreader/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 Erik Geiser and Christian Muehlhaeuser
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/muesli/cancelreader/README.md b/vendor/github.com/muesli/cancelreader/README.md
new file mode 100644
index 00000000..83609fbc
--- /dev/null
+++ b/vendor/github.com/muesli/cancelreader/README.md
@@ -0,0 +1,64 @@
+# CancelReader
+
+[](https://github.com/muesli/cancelreader/releases)
+[](https://pkg.go.dev/github.com/muesli/cancelreader)
+[](/LICENSE)
+[](https://github.com/muesli/cancelreader/actions)
+[](https://goreportcard.com/report/muesli/cancelreader)
+
+A cancelable reader for Go
+
+This package is based on the fantastic work of [Erik Geiser](https://github.com/erikgeiser)
+in Charm's [Bubble Tea](https://github.com/charmbracelet/bubbletea) framework.
+
+## Usage
+
+`NewReader` returns a reader with a `Cancel` function. If the input reader is a
+`File`, the cancel function can be used to interrupt a blocking `Read` call.
+In this case, the cancel function returns true if the call was canceled
+successfully. If the input reader is not a `File`, the cancel function does
+nothing and always returns false.
+
+```go
+r, err := cancelreader.NewReader(file)
+if err != nil {
+ // handle error
+ ...
+}
+
+// cancel after five seconds
+go func() {
+ time.Sleep(5 * time.Second)
+ r.Cancel()
+}()
+
+// keep reading
+for {
+ var buf [1024]byte
+ _, err := r.Read(buf[:])
+
+ if errors.Is(err, cancelreader.ErrCanceled) {
+ fmt.Println("canceled!")
+ break
+ }
+ if err != nil {
+ // handle other errors
+ ...
+ }
+
+ // handle data
+ ...
+}
+```
+
+## Implementations
+
+- The Linux implementation is based on the epoll mechanism
+- The BSD and macOS implementation is based on the kqueue mechanism
+- The generic Unix implementation is based on the posix select syscall
+
+## Caution
+
+The Windows implementation is based on WaitForMultipleObject with overlapping
+reads from CONIN$. At this point it only supports canceling reads from
+`os.Stdin`.
diff --git a/vendor/github.com/muesli/cancelreader/cancelreader.go b/vendor/github.com/muesli/cancelreader/cancelreader.go
new file mode 100644
index 00000000..18d38255
--- /dev/null
+++ b/vendor/github.com/muesli/cancelreader/cancelreader.go
@@ -0,0 +1,93 @@
+package cancelreader
+
+import (
+ "fmt"
+ "io"
+ "sync"
+)
+
+// ErrCanceled gets returned when trying to read from a canceled reader.
+var ErrCanceled = fmt.Errorf("read canceled")
+
+// CancelReader is a io.Reader whose Read() calls can be canceled without data
+// being consumed. The cancelReader has to be closed.
+type CancelReader interface {
+ io.ReadCloser
+
+ // Cancel cancels ongoing and future reads an returns true if it succeeded.
+ Cancel() bool
+}
+
+// File represents an input/output resource with a file descriptor.
+type File interface {
+ io.ReadWriteCloser
+
+ // Fd returns its file descriptor
+ Fd() uintptr
+
+ // Name returns its file name.
+ Name() string
+}
+
+// fallbackCancelReader implements cancelReader but does not actually support
+// cancelation during an ongoing Read() call. Thus, Cancel() always returns
+// false. However, after calling Cancel(), new Read() calls immediately return
+// errCanceled and don't consume any data anymore.
+type fallbackCancelReader struct {
+ r io.Reader
+ cancelMixin
+}
+
+// newFallbackCancelReader is a fallback for NewReader that cannot actually
+// cancel an ongoing read but will immediately return on future reads if it has
+// been canceled.
+func newFallbackCancelReader(reader io.Reader) (CancelReader, error) {
+ return &fallbackCancelReader{r: reader}, nil
+}
+
+func (r *fallbackCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ n, err := r.r.Read(data)
+ /*
+ If the underlying reader is a blocking reader (e.g. an open connection),
+ it might happen that 1 goroutine cancels the reader while its stuck in
+ the read call waiting for something.
+ If that happens, we should still cancel the read.
+ */
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+ return n, err // nolint: wrapcheck
+}
+
+func (r *fallbackCancelReader) Cancel() bool {
+ r.setCanceled()
+ return false
+}
+
+func (r *fallbackCancelReader) Close() error {
+ return nil
+}
+
+// cancelMixin represents a goroutine-safe cancelation status.
+type cancelMixin struct {
+ unsafeCanceled bool
+ lock sync.Mutex
+}
+
+func (c *cancelMixin) isCanceled() bool {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ return c.unsafeCanceled
+}
+
+func (c *cancelMixin) setCanceled() {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ c.unsafeCanceled = true
+}
diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_bsd.go b/vendor/github.com/muesli/cancelreader/cancelreader_bsd.go
new file mode 100644
index 00000000..3ddb6cff
--- /dev/null
+++ b/vendor/github.com/muesli/cancelreader/cancelreader_bsd.go
@@ -0,0 +1,146 @@
+//go:build darwin || freebsd || netbsd || openbsd || dragonfly
+// +build darwin freebsd netbsd openbsd dragonfly
+
+package cancelreader
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "golang.org/x/sys/unix"
+)
+
+// NewReader returns a reader and a cancel function. If the input reader is a
+// File, the cancel function can be used to interrupt a blocking read call.
+// In this case, the cancel function returns true if the call was canceled
+// successfully. If the input reader is not a File, the cancel function
+// does nothing and always returns false. The BSD and macOS implementation is
+// based on the kqueue mechanism.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ file, ok := reader.(File)
+ if !ok {
+ return newFallbackCancelReader(reader)
+ }
+
+ // kqueue returns instantly when polling /dev/tty so fallback to select
+ if file.Name() == "/dev/tty" {
+ return newSelectCancelReader(reader)
+ }
+
+ kQueue, err := unix.Kqueue()
+ if err != nil {
+ return nil, fmt.Errorf("create kqueue: %w", err)
+ }
+
+ r := &kqueueCancelReader{
+ file: file,
+ kQueue: kQueue,
+ }
+
+ r.cancelSignalReader, r.cancelSignalWriter, err = os.Pipe()
+ if err != nil {
+ _ = unix.Close(kQueue)
+ return nil, err
+ }
+
+ unix.SetKevent(&r.kQueueEvents[0], int(file.Fd()), unix.EVFILT_READ, unix.EV_ADD)
+ unix.SetKevent(&r.kQueueEvents[1], int(r.cancelSignalReader.Fd()), unix.EVFILT_READ, unix.EV_ADD)
+
+ return r, nil
+}
+
+type kqueueCancelReader struct {
+ file File
+ cancelSignalReader File
+ cancelSignalWriter File
+ cancelMixin
+ kQueue int
+ kQueueEvents [2]unix.Kevent_t
+}
+
+func (r *kqueueCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ err := r.wait()
+ if err != nil {
+ if errors.Is(err, ErrCanceled) {
+ // remove signal from pipe
+ var b [1]byte
+ _, errRead := r.cancelSignalReader.Read(b[:])
+ if errRead != nil {
+ return 0, fmt.Errorf("reading cancel signal: %w", errRead)
+ }
+ }
+
+ return 0, err
+ }
+
+ return r.file.Read(data)
+}
+
+func (r *kqueueCancelReader) Cancel() bool {
+ r.setCanceled()
+
+ // send cancel signal
+ _, err := r.cancelSignalWriter.Write([]byte{'c'})
+ return err == nil
+}
+
+func (r *kqueueCancelReader) Close() error {
+ var errMsgs []string
+
+ // close kqueue
+ err := unix.Close(r.kQueue)
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing kqueue: %v", err))
+ }
+
+ // close pipe
+ err = r.cancelSignalWriter.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal writer: %v", err))
+ }
+
+ err = r.cancelSignalReader.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal reader: %v", err))
+ }
+
+ if len(errMsgs) > 0 {
+ return fmt.Errorf(strings.Join(errMsgs, ", "))
+ }
+
+ return nil
+}
+
+func (r *kqueueCancelReader) wait() error {
+ events := make([]unix.Kevent_t, 1)
+
+ for {
+ _, err := unix.Kevent(r.kQueue, r.kQueueEvents[:], events, nil)
+ if errors.Is(err, unix.EINTR) {
+ continue // try again if the syscall was interrupted
+ }
+
+ if err != nil {
+ return fmt.Errorf("kevent: %w", err)
+ }
+
+ break
+ }
+
+ ident := uint64(events[0].Ident)
+ switch ident {
+ case uint64(r.file.Fd()):
+ return nil
+ case uint64(r.cancelSignalReader.Fd()):
+ return ErrCanceled
+ }
+
+ return fmt.Errorf("unknown error")
+}
diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_default.go b/vendor/github.com/muesli/cancelreader/cancelreader_default.go
new file mode 100644
index 00000000..8e275fa4
--- /dev/null
+++ b/vendor/github.com/muesli/cancelreader/cancelreader_default.go
@@ -0,0 +1,12 @@
+//go:build !darwin && !windows && !linux && !solaris && !freebsd && !netbsd && !openbsd && !dragonfly
+// +build !darwin,!windows,!linux,!solaris,!freebsd,!netbsd,!openbsd,!dragonfly
+
+package cancelreader
+
+import "io"
+
+// NewReader returns a fallbackCancelReader that satisfies the CancelReader but
+// does not actually support cancellation.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ return newFallbackCancelReader(reader)
+}
diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_linux.go b/vendor/github.com/muesli/cancelreader/cancelreader_linux.go
new file mode 100644
index 00000000..09f7369f
--- /dev/null
+++ b/vendor/github.com/muesli/cancelreader/cancelreader_linux.go
@@ -0,0 +1,154 @@
+//go:build linux
+// +build linux
+
+package cancelreader
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "golang.org/x/sys/unix"
+)
+
+// NewReader returns a reader and a cancel function. If the input reader is a
+// File, the cancel function can be used to interrupt a blocking read call.
+// In this case, the cancel function returns true if the call was canceled
+// successfully. If the input reader is not a File, the cancel function
+// does nothing and always returns false. The Linux implementation is based on
+// the epoll mechanism.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ file, ok := reader.(File)
+ if !ok {
+ return newFallbackCancelReader(reader)
+ }
+
+ epoll, err := unix.EpollCreate1(0)
+ if err != nil {
+ return nil, fmt.Errorf("create epoll: %w", err)
+ }
+
+ r := &epollCancelReader{
+ file: file,
+ epoll: epoll,
+ }
+
+ r.cancelSignalReader, r.cancelSignalWriter, err = os.Pipe()
+ if err != nil {
+ _ = unix.Close(epoll)
+ return nil, err
+ }
+
+ err = unix.EpollCtl(epoll, unix.EPOLL_CTL_ADD, int(file.Fd()), &unix.EpollEvent{
+ Events: unix.EPOLLIN,
+ Fd: int32(file.Fd()),
+ })
+ if err != nil {
+ _ = unix.Close(epoll)
+ return nil, fmt.Errorf("add reader to epoll interest list")
+ }
+
+ err = unix.EpollCtl(epoll, unix.EPOLL_CTL_ADD, int(r.cancelSignalReader.Fd()), &unix.EpollEvent{
+ Events: unix.EPOLLIN,
+ Fd: int32(r.cancelSignalReader.Fd()),
+ })
+ if err != nil {
+ _ = unix.Close(epoll)
+ return nil, fmt.Errorf("add reader to epoll interest list")
+ }
+
+ return r, nil
+}
+
+type epollCancelReader struct {
+ file File
+ cancelSignalReader File
+ cancelSignalWriter File
+ cancelMixin
+ epoll int
+}
+
+func (r *epollCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ err := r.wait()
+ if err != nil {
+ if errors.Is(err, ErrCanceled) {
+ // remove signal from pipe
+ var b [1]byte
+ _, readErr := r.cancelSignalReader.Read(b[:])
+ if readErr != nil {
+ return 0, fmt.Errorf("reading cancel signal: %w", readErr)
+ }
+ }
+
+ return 0, err
+ }
+
+ return r.file.Read(data)
+}
+
+func (r *epollCancelReader) Cancel() bool {
+ r.setCanceled()
+
+ // send cancel signal
+ _, err := r.cancelSignalWriter.Write([]byte{'c'})
+ return err == nil
+}
+
+func (r *epollCancelReader) Close() error {
+ var errMsgs []string
+
+ // close kqueue
+ err := unix.Close(r.epoll)
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing epoll: %v", err))
+ }
+
+ // close pipe
+ err = r.cancelSignalWriter.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal writer: %v", err))
+ }
+
+ err = r.cancelSignalReader.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal reader: %v", err))
+ }
+
+ if len(errMsgs) > 0 {
+ return fmt.Errorf(strings.Join(errMsgs, ", "))
+ }
+
+ return nil
+}
+
+func (r *epollCancelReader) wait() error {
+ events := make([]unix.EpollEvent, 1)
+
+ for {
+ _, err := unix.EpollWait(r.epoll, events, -1)
+ if errors.Is(err, unix.EINTR) {
+ continue // try again if the syscall was interrupted
+ }
+
+ if err != nil {
+ return fmt.Errorf("kevent: %w", err)
+ }
+
+ break
+ }
+
+ switch events[0].Fd {
+ case int32(r.file.Fd()):
+ return nil
+ case int32(r.cancelSignalReader.Fd()):
+ return ErrCanceled
+ }
+
+ return fmt.Errorf("unknown error")
+}
diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_select.go b/vendor/github.com/muesli/cancelreader/cancelreader_select.go
new file mode 100644
index 00000000..03f2a3e1
--- /dev/null
+++ b/vendor/github.com/muesli/cancelreader/cancelreader_select.go
@@ -0,0 +1,136 @@
+//go:build solaris || darwin || freebsd || netbsd || openbsd || dragonfly
+// +build solaris darwin freebsd netbsd openbsd dragonfly
+
+package cancelreader
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "golang.org/x/sys/unix"
+)
+
+// newSelectCancelReader returns a reader and a cancel function. If the input
+// reader is a File, the cancel function can be used to interrupt a
+// blocking call read call. In this case, the cancel function returns true if
+// the call was canceled successfully. If the input reader is not a File or
+// the file descriptor is 1024 or larger, the cancel function does nothing and
+// always returns false. The generic unix implementation is based on the posix
+// select syscall.
+func newSelectCancelReader(reader io.Reader) (CancelReader, error) {
+ file, ok := reader.(File)
+ if !ok || file.Fd() >= unix.FD_SETSIZE {
+ return newFallbackCancelReader(reader)
+ }
+ r := &selectCancelReader{file: file}
+
+ var err error
+
+ r.cancelSignalReader, r.cancelSignalWriter, err = os.Pipe()
+ if err != nil {
+ return nil, err
+ }
+
+ return r, nil
+}
+
+type selectCancelReader struct {
+ file File
+ cancelSignalReader File
+ cancelSignalWriter File
+ cancelMixin
+}
+
+func (r *selectCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ for {
+ err := waitForRead(r.file, r.cancelSignalReader)
+ if err != nil {
+ if errors.Is(err, unix.EINTR) {
+ continue // try again if the syscall was interrupted
+ }
+
+ if errors.Is(err, ErrCanceled) {
+ // remove signal from pipe
+ var b [1]byte
+ _, readErr := r.cancelSignalReader.Read(b[:])
+ if readErr != nil {
+ return 0, fmt.Errorf("reading cancel signal: %w", readErr)
+ }
+ }
+
+ return 0, err
+ }
+
+ return r.file.Read(data)
+ }
+}
+
+func (r *selectCancelReader) Cancel() bool {
+ r.setCanceled()
+
+ // send cancel signal
+ _, err := r.cancelSignalWriter.Write([]byte{'c'})
+ return err == nil
+}
+
+func (r *selectCancelReader) Close() error {
+ var errMsgs []string
+
+ // close pipe
+ err := r.cancelSignalWriter.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal writer: %v", err))
+ }
+
+ err = r.cancelSignalReader.Close()
+ if err != nil {
+ errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal reader: %v", err))
+ }
+
+ if len(errMsgs) > 0 {
+ return fmt.Errorf(strings.Join(errMsgs, ", "))
+ }
+
+ return nil
+}
+
+func waitForRead(reader, abort File) error {
+ readerFd := int(reader.Fd())
+ abortFd := int(abort.Fd())
+
+ maxFd := readerFd
+ if abortFd > maxFd {
+ maxFd = abortFd
+ }
+
+ // this is a limitation of the select syscall
+ if maxFd >= unix.FD_SETSIZE {
+ return fmt.Errorf("cannot select on file descriptor %d which is larger than 1024", maxFd)
+ }
+
+ fdSet := &unix.FdSet{}
+ fdSet.Set(int(reader.Fd()))
+ fdSet.Set(int(abort.Fd()))
+
+ _, err := unix.Select(maxFd+1, fdSet, nil, nil, nil)
+ if err != nil {
+ return fmt.Errorf("select: %w", err)
+ }
+
+ if fdSet.IsSet(abortFd) {
+ return ErrCanceled
+ }
+
+ if fdSet.IsSet(readerFd) {
+ return nil
+ }
+
+ return fmt.Errorf("select returned without setting a file descriptor")
+}
diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_unix.go b/vendor/github.com/muesli/cancelreader/cancelreader_unix.go
new file mode 100644
index 00000000..3c10ee09
--- /dev/null
+++ b/vendor/github.com/muesli/cancelreader/cancelreader_unix.go
@@ -0,0 +1,18 @@
+//go:build solaris
+// +build solaris
+
+package cancelreader
+
+import (
+ "io"
+)
+
+// NewReader returns a reader and a cancel function. If the input reader is a
+// File, the cancel function can be used to interrupt a blocking read call.
+// In this case, the cancel function returns true if the call was canceled
+// successfully. If the input reader is not a File or the file descriptor
+// is 1024 or larger, the cancel function does nothing and always returns false.
+// The generic unix implementation is based on the posix select syscall.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ return newSelectCancelReader(reader)
+}
diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_windows.go b/vendor/github.com/muesli/cancelreader/cancelreader_windows.go
new file mode 100644
index 00000000..c1dc8d50
--- /dev/null
+++ b/vendor/github.com/muesli/cancelreader/cancelreader_windows.go
@@ -0,0 +1,244 @@
+//go:build windows
+// +build windows
+
+package cancelreader
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "syscall"
+ "time"
+ "unicode/utf16"
+
+ "golang.org/x/sys/windows"
+)
+
+var fileShareValidFlags uint32 = 0x00000007
+
+// NewReader returns a reader and a cancel function. If the input reader is a
+// File with the same file descriptor as os.Stdin, the cancel function can
+// be used to interrupt a blocking read call. In this case, the cancel function
+// returns true if the call was canceled successfully. If the input reader is
+// not a File with the same file descriptor as os.Stdin, the cancel
+// function does nothing and always returns false. The Windows implementation
+// is based on WaitForMultipleObject with overlapping reads from CONIN$.
+func NewReader(reader io.Reader) (CancelReader, error) {
+ if f, ok := reader.(File); !ok || f.Fd() != os.Stdin.Fd() {
+ return newFallbackCancelReader(reader)
+ }
+
+ // it is necessary to open CONIN$ (NOT windows.STD_INPUT_HANDLE) in
+ // overlapped mode to be able to use it with WaitForMultipleObjects.
+ conin, err := windows.CreateFile(
+ &(utf16.Encode([]rune("CONIN$\x00"))[0]), windows.GENERIC_READ|windows.GENERIC_WRITE,
+ fileShareValidFlags, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED, 0)
+ if err != nil {
+ return nil, fmt.Errorf("open CONIN$ in overlapping mode: %w", err)
+ }
+
+ resetConsole, err := prepareConsole(conin)
+ if err != nil {
+ return nil, fmt.Errorf("prepare console: %w", err)
+ }
+
+ // flush input, otherwise it can contain events which trigger
+ // WaitForMultipleObjects but which ReadFile cannot read, resulting in an
+ // un-cancelable read
+ err = flushConsoleInputBuffer(conin)
+ if err != nil {
+ return nil, fmt.Errorf("flush console input buffer: %w", err)
+ }
+
+ cancelEvent, err := windows.CreateEvent(nil, 0, 0, nil)
+ if err != nil {
+ return nil, fmt.Errorf("create stop event: %w", err)
+ }
+
+ return &winCancelReader{
+ conin: conin,
+ cancelEvent: cancelEvent,
+ resetConsole: resetConsole,
+ blockingReadSignal: make(chan struct{}, 1),
+ }, nil
+}
+
+type winCancelReader struct {
+ conin windows.Handle
+ cancelEvent windows.Handle
+ cancelMixin
+
+ resetConsole func() error
+ blockingReadSignal chan struct{}
+}
+
+func (r *winCancelReader) Read(data []byte) (int, error) {
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ err := r.wait()
+ if err != nil {
+ return 0, err
+ }
+
+ if r.isCanceled() {
+ return 0, ErrCanceled
+ }
+
+ // windows.Read does not work on overlapping windows.Handles
+ return r.readAsync(data)
+}
+
+// Cancel cancels ongoing and future Read() calls and returns true if the
+// cancelation of the ongoing Read() was successful. On Windows Terminal,
+// WaitForMultipleObjects sometimes immediately returns without input being
+// available. In this case, graceful cancelation is not possible and Cancel()
+// returns false.
+func (r *winCancelReader) Cancel() bool {
+ r.setCanceled()
+
+ select {
+ case r.blockingReadSignal <- struct{}{}:
+ err := windows.SetEvent(r.cancelEvent)
+ if err != nil {
+ return false
+ }
+ <-r.blockingReadSignal
+ case <-time.After(100 * time.Millisecond):
+ // Read() hangs in a GetOverlappedResult which is likely due to
+ // WaitForMultipleObjects returning without input being available
+ // so we cannot cancel this ongoing read.
+ return false
+ }
+
+ return true
+}
+
+func (r *winCancelReader) Close() error {
+ err := windows.CloseHandle(r.cancelEvent)
+ if err != nil {
+ return fmt.Errorf("closing cancel event handle: %w", err)
+ }
+
+ err = r.resetConsole()
+ if err != nil {
+ return err
+ }
+
+ err = windows.Close(r.conin)
+ if err != nil {
+ return fmt.Errorf("closing CONIN$")
+ }
+
+ return nil
+}
+
+func (r *winCancelReader) wait() error {
+ event, err := windows.WaitForMultipleObjects([]windows.Handle{r.conin, r.cancelEvent}, false, windows.INFINITE)
+ switch {
+ case windows.WAIT_OBJECT_0 <= event && event < windows.WAIT_OBJECT_0+2:
+ if event == windows.WAIT_OBJECT_0+1 {
+ return ErrCanceled
+ }
+
+ if event == windows.WAIT_OBJECT_0 {
+ return nil
+ }
+
+ return fmt.Errorf("unexpected wait object is ready: %d", event-windows.WAIT_OBJECT_0)
+ case windows.WAIT_ABANDONED <= event && event < windows.WAIT_ABANDONED+2:
+ return fmt.Errorf("abandoned")
+ case event == uint32(windows.WAIT_TIMEOUT):
+ return fmt.Errorf("timeout")
+ case event == windows.WAIT_FAILED:
+ return fmt.Errorf("failed")
+ default:
+ return fmt.Errorf("unexpected error: %w", error(err))
+ }
+}
+
+// readAsync is necessary to read from a windows.Handle in overlapping mode.
+func (r *winCancelReader) readAsync(data []byte) (int, error) {
+ hevent, err := windows.CreateEvent(nil, 0, 0, nil)
+ if err != nil {
+ return 0, fmt.Errorf("create event: %w", err)
+ }
+
+ overlapped := windows.Overlapped{
+ HEvent: hevent,
+ }
+
+ var n uint32
+
+ err = windows.ReadFile(r.conin, data, &n, &overlapped)
+ if err != nil && err != windows.ERROR_IO_PENDING {
+ return int(n), err
+ }
+
+ r.blockingReadSignal <- struct{}{}
+ err = windows.GetOverlappedResult(r.conin, &overlapped, &n, true)
+ if err != nil {
+ return int(n), nil
+ }
+ <-r.blockingReadSignal
+
+ return int(n), nil
+}
+
+func prepareConsole(input windows.Handle) (reset func() error, err error) {
+ var originalMode uint32
+
+ err = windows.GetConsoleMode(input, &originalMode)
+ if err != nil {
+ return nil, fmt.Errorf("get console mode: %w", err)
+ }
+
+ var newMode uint32
+ newMode &^= windows.ENABLE_ECHO_INPUT
+ newMode &^= windows.ENABLE_LINE_INPUT
+ newMode &^= windows.ENABLE_MOUSE_INPUT
+ newMode &^= windows.ENABLE_WINDOW_INPUT
+ newMode &^= windows.ENABLE_PROCESSED_INPUT
+
+ newMode |= windows.ENABLE_EXTENDED_FLAGS
+ newMode |= windows.ENABLE_INSERT_MODE
+ newMode |= windows.ENABLE_QUICK_EDIT_MODE
+
+ // Enabling virtual terminal input is necessary for processing certain
+ // types of input like X10 mouse events and arrows keys with the current
+ // bytes-based input reader. It does, however, prevent cancelReader from
+ // being able to cancel input. The planned solution for this is to read
+ // Windows events in a more native fashion, rather than the current simple
+ // bytes-based input reader which works well on unix systems.
+ newMode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
+
+ err = windows.SetConsoleMode(input, newMode)
+ if err != nil {
+ return nil, fmt.Errorf("set console mode: %w", err)
+ }
+
+ return func() error {
+ err := windows.SetConsoleMode(input, originalMode)
+ if err != nil {
+ return fmt.Errorf("reset console mode: %w", err)
+ }
+
+ return nil
+ }, nil
+}
+
+var (
+ modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
+ procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer")
+)
+
+func flushConsoleInputBuffer(consoleInput windows.Handle) error {
+ r, _, e := syscall.Syscall(procFlushConsoleInputBuffer.Addr(), 1,
+ uintptr(consoleInput), 0, 0)
+ if r == 0 {
+ return error(e)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/muesli/termenv/README.md b/vendor/github.com/muesli/termenv/README.md
deleted file mode 100644
index fa7929d4..00000000
--- a/vendor/github.com/muesli/termenv/README.md
+++ /dev/null
@@ -1,431 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-`termenv` lets you safely use advanced styling options on the terminal. It
-gathers information about the terminal environment in terms of its ANSI & color
-support and offers you convenient methods to colorize and style your output,
-without you having to deal with all kinds of weird ANSI escape sequences and
-color conversions.
-
-## Features
-
-- RGB/TrueColor support
-- Detects the supported color range of your terminal
-- Automatically converts colors to the best matching, available colors
-- Terminal theme (light/dark) detection
-- Chainable syntax
-- Nested styles
-
-## Installation
-
-```bash
-go get github.com/muesli/termenv
-```
-
-## Usage
-
-```go
-output := termenv.NewOutput(os.Stdout)
-```
-
-`termenv` queries the terminal's capabilities it is running in, so you can
-safely use advanced features, like RGB colors or ANSI styles. `output.Profile`
-returns the supported profile:
-
-- `termenv.Ascii` - no ANSI support detected, ASCII only
-- `termenv.ANSI` - 16 color ANSI support
-- `termenv.ANSI256` - Extended 256 color ANSI support
-- `termenv.TrueColor` - RGB/TrueColor support
-
-Alternatively, you can use `termenv.EnvColorProfile` which evaluates the
-terminal like `ColorProfile`, but also respects the `NO_COLOR` and
-`CLICOLOR_FORCE` environment variables.
-
-You can also query the terminal for its color scheme, so you know whether your
-app is running in a light- or dark-themed environment:
-
-```go
-// Returns terminal's foreground color
-color := output.ForegroundColor()
-
-// Returns terminal's background color
-color := output.BackgroundColor()
-
-// Returns whether terminal uses a dark-ish background
-darkTheme := output.HasDarkBackground()
-```
-
-### Manual Profile Selection
-
-If you don't want to rely on the automatic detection, you can manually select
-the profile you want to use:
-
-```go
-output := termenv.NewOutput(os.Stdout, termenv.WithProfile(termenv.TrueColor))
-```
-
-## Colors
-
-`termenv` supports multiple color profiles: Ascii (black & white only),
-ANSI (16 colors), ANSI Extended (256 colors), and TrueColor (24-bit RGB). Colors
-will automatically be degraded to the best matching available color in the
-desired profile:
-
-`TrueColor` => `ANSI 256 Colors` => `ANSI 16 Colors` => `Ascii`
-
-```go
-s := output.String("Hello World")
-
-// Supports hex values
-// Will automatically degrade colors on terminals not supporting RGB
-s.Foreground(output.Color("#abcdef"))
-// but also supports ANSI colors (0-255)
-s.Background(output.Color("69"))
-// ...or the color.Color interface
-s.Foreground(output.FromColor(color.RGBA{255, 128, 0, 255}))
-
-// Combine fore- & background colors
-s.Foreground(output.Color("#ffffff")).Background(output.Color("#0000ff"))
-
-// Supports the fmt.Stringer interface
-fmt.Println(s)
-```
-
-## Styles
-
-You can use a chainable syntax to compose your own styles:
-
-```go
-s := output.String("foobar")
-
-// Text styles
-s.Bold()
-s.Faint()
-s.Italic()
-s.CrossOut()
-s.Underline()
-s.Overline()
-
-// Reverse swaps current fore- & background colors
-s.Reverse()
-
-// Blinking text
-s.Blink()
-
-// Combine multiple options
-s.Bold().Underline()
-```
-
-## Template Helpers
-
-`termenv` provides a set of helper functions to style your Go templates:
-
-```go
-// load template helpers
-f := output.TemplateFuncs()
-tpl := template.New("tpl").Funcs(f)
-
-// apply bold style in a template
-bold := `{{ Bold "Hello World" }}`
-
-// examples for colorized templates
-col := `{{ Color "#ff0000" "#0000ff" "Red on Blue" }}`
-fg := `{{ Foreground "#ff0000" "Red Foreground" }}`
-bg := `{{ Background "#0000ff" "Blue Background" }}`
-
-// wrap styles
-wrap := `{{ Bold (Underline "Hello World") }}`
-
-// parse and render
-tpl, err = tpl.Parse(bold)
-
-var buf bytes.Buffer
-tpl.Execute(&buf, nil)
-fmt.Println(&buf)
-```
-
-Other available helper functions are: `Faint`, `Italic`, `CrossOut`,
-`Underline`, `Overline`, `Reverse`, and `Blink`.
-
-## Positioning
-
-```go
-// Move the cursor to a given position
-output.MoveCursor(row, column)
-
-// Save the cursor position
-output.SaveCursorPosition()
-
-// Restore a saved cursor position
-output.RestoreCursorPosition()
-
-// Move the cursor up a given number of lines
-output.CursorUp(n)
-
-// Move the cursor down a given number of lines
-output.CursorDown(n)
-
-// Move the cursor up a given number of lines
-output.CursorForward(n)
-
-// Move the cursor backwards a given number of cells
-output.CursorBack(n)
-
-// Move the cursor down a given number of lines and place it at the beginning
-// of the line
-output.CursorNextLine(n)
-
-// Move the cursor up a given number of lines and place it at the beginning of
-// the line
-output.CursorPrevLine(n)
-```
-
-## Screen
-
-```go
-// Reset the terminal to its default style, removing any active styles
-output.Reset()
-
-// RestoreScreen restores a previously saved screen state
-output.RestoreScreen()
-
-// SaveScreen saves the screen state
-output.SaveScreen()
-
-// Switch to the altscreen. The former view can be restored with ExitAltScreen()
-output.AltScreen()
-
-// Exit the altscreen and return to the former terminal view
-output.ExitAltScreen()
-
-// Clear the visible portion of the terminal
-output.ClearScreen()
-
-// Clear the current line
-output.ClearLine()
-
-// Clear a given number of lines
-output.ClearLines(n)
-
-// Set the scrolling region of the terminal
-output.ChangeScrollingRegion(top, bottom)
-
-// Insert the given number of lines at the top of the scrollable region, pushing
-// lines below down
-output.InsertLines(n)
-
-// Delete the given number of lines, pulling any lines in the scrollable region
-// below up
-output.DeleteLines(n)
-```
-
-## Session
-
-```go
-// SetWindowTitle sets the terminal window title
-output.SetWindowTitle(title)
-
-// SetForegroundColor sets the default foreground color
-output.SetForegroundColor(color)
-
-// SetBackgroundColor sets the default background color
-output.SetBackgroundColor(color)
-
-// SetCursorColor sets the cursor color
-output.SetCursorColor(color)
-
-// Hide the cursor
-output.HideCursor()
-
-// Show the cursor
-output.ShowCursor()
-
-// Copy to clipboard
-output.Copy(message)
-
-// Copy to primary clipboard (X11)
-output.CopyPrimary(message)
-
-// Trigger notification
-output.Notify(title, body)
-```
-
-## Mouse
-
-```go
-// Enable X10 mouse mode, only button press events are sent
-output.EnableMousePress()
-
-// Disable X10 mouse mode
-output.DisableMousePress()
-
-// Enable Mouse Tracking mode
-output.EnableMouse()
-
-// Disable Mouse Tracking mode
-output.DisableMouse()
-
-// Enable Hilite Mouse Tracking mode
-output.EnableMouseHilite()
-
-// Disable Hilite Mouse Tracking mode
-output.DisableMouseHilite()
-
-// Enable Cell Motion Mouse Tracking mode
-output.EnableMouseCellMotion()
-
-// Disable Cell Motion Mouse Tracking mode
-output.DisableMouseCellMotion()
-
-// Enable All Motion Mouse mode
-output.EnableMouseAllMotion()
-
-// Disable All Motion Mouse mode
-output.DisableMouseAllMotion()
-```
-
-## Bracketed Paste
-
-```go
-// Enables bracketed paste mode
-termenv.EnableBracketedPaste()
-
-// Disables bracketed paste mode
-termenv.DisableBracketedPaste()
-```
-
-## Terminal Feature Support
-
-### Color Support
-
-- 24-bit (RGB): alacritty, foot, iTerm, kitty, Konsole, st, tmux, vte-based, wezterm, Ghostty, Windows Terminal
-- 8-bit (256): rxvt, screen, xterm, Apple Terminal
-- 4-bit (16): Linux Console
-
-### Control Sequences
-
-
-Click to show feature matrix
-
-| Terminal | Query Color Scheme | Query Cursor Position | Set Window Title | Change Cursor Color | Change Default Foreground Setting | Change Default Background Setting | Bracketed Paste | Extended Mouse (SGR) | Pixels Mouse (SGR-Pixels) |
-| ---------------- | :----------------: | :-------------------: | :--------------: | :-----------------: | :-------------------------------: | :-------------------------------: | :-------------: | :------------------: | :-----------------------: |
-| alacritty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| foot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| kitty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| Konsole | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| rxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
-| urxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| screen | ⛔[^mux] | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
-| st | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| tmux | ⛔[^mux] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| vte-based[^vte] | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
-| wezterm | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
-| xterm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
-| Linux Console | ❌ | ✅ | ⛔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
-| Apple Terminal | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
-| iTerm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
-| Windows cmd | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
-| Windows Terminal | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
-
-[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal.
-[^mux]: Unavailable as multiplexers (like tmux or screen) can be connected to multiple terminals (with different color settings) at the same time.
-
-You can help improve this list! Check out [how to](ansi_compat.md) and open an issue or pull request.
-
-
-
-### System Commands
-
-
-Click to show feature matrix
-
-| Terminal | Copy to Clipboard (OSC52) | Hyperlinks (OSC8) | Notifications (OSC777) |
-| ---------------- | :-----------------------: | :---------------: | :--------------------: |
-| alacritty | ✅ | ✅[^alacritty] | ❌ |
-| foot | ✅ | ✅ | ✅ |
-| kitty | ✅ | ✅ | ✅ |
-| Konsole | ❌[^konsole] | ✅ | ❌ |
-| rxvt | ❌ | ❌ | ❌ |
-| urxvt | ✅[^urxvt] | ❌ | ✅ |
-| screen | ✅ | ❌[^screen] | ❌ |
-| st | ✅ | ❌ | ❌ |
-| tmux | ✅ | ❌[^tmux] | ❌ |
-| vte-based[^vte] | ❌[^vte] | ✅ | ❌ |
-| wezterm | ✅ | ✅ | ❌ |
-| xterm | ✅ | ❌ | ❌ |
-| Linux Console | ⛔ | ⛔ | ❌ |
-| Apple Terminal | ✅[^apple] | ❌ | ❌ |
-| iTerm | ✅ | ✅ | ❌ |
-| Windows cmd | ❌ | ❌ | ❌ |
-| Windows Terminal | ✅ | ✅ | ❌ |
-
-[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal. OSC52 is not supported, see [issue#2495](https://gitlab.gnome.org/GNOME/vte/-/issues/2495).
-[^urxvt]: Workaround for urxvt not supporting OSC52. See [this](https://unix.stackexchange.com/a/629485) for more information.
-[^konsole]: OSC52 is not supported, for more info see [bug#372116](https://bugs.kde.org/show_bug.cgi?id=372116).
-[^apple]: OSC52 works with a [workaround](https://github.com/roy2220/osc52pty).
-[^tmux]: OSC8 is not supported, for more info see [issue#911](https://github.com/tmux/tmux/issues/911).
-[^screen]: OSC8 is not supported, for more info see [bug#50952](https://savannah.gnu.org/bugs/index.php?50952).
-[^alacritty]: OSC8 is supported since [v0.11.0](https://github.com/alacritty/alacritty/releases/tag/v0.11.0)
-
-
-
-## Platform Support
-
-`termenv` works on Unix systems (like Linux, macOS, or BSD) and Windows. While
-terminal applications on Unix support ANSI styling out-of-the-box, on Windows
-you need to enable ANSI processing in your application first:
-
-```go
- restoreConsole, err := termenv.EnableVirtualTerminalProcessing(termenv.DefaultOutput())
- if err != nil {
- panic(err)
- }
- defer restoreConsole()
-```
-
-The above code is safe to include on non-Windows systems or when os.Stdout does
-not refer to a terminal (e.g. in tests).
-
-## Color Chart
-
-
-
-You can find the source code used to create this chart in `termenv`'s examples.
-
-## Related Projects
-
-- [reflow](https://github.com/muesli/reflow) - ANSI-aware text operations
-- [Lip Gloss](https://github.com/charmbracelet/lipgloss) - style definitions for nice terminal layouts 👄
-- [ansi](https://github.com/muesli/ansi) - ANSI sequence helpers
-
-## termenv in the Wild
-
-Need some inspiration or just want to see how others are using `termenv`? Check
-out these projects:
-
-- [Bubble Tea](https://github.com/charmbracelet/bubbletea) - a powerful little TUI framework 🏗
-- [Glamour](https://github.com/charmbracelet/glamour) - stylesheet-based markdown rendering for your CLI apps 💇🏻♀️
-- [Glow](https://github.com/charmbracelet/glow) - a markdown renderer for the command-line 💅🏻
-- [duf](https://github.com/muesli/duf) - Disk Usage/Free Utility - a better 'df' alternative
-- [gitty](https://github.com/muesli/gitty) - contextual information about your git projects
-- [slides](https://github.com/maaslalani/slides) - terminal-based presentation tool
-
-## Feedback
-
-Got some feedback or suggestions? Please open an issue or drop me a note!
-
-- [Twitter](https://twitter.com/mueslix)
-- [The Fediverse](https://mastodon.social/@fribbledom)
-
-## License
-
-[MIT](https://github.com/muesli/termenv/raw/master/LICENSE)
diff --git a/vendor/github.com/muesli/termenv/ansi_compat.md b/vendor/github.com/muesli/termenv/ansi_compat.md
deleted file mode 100644
index 6b68a3a9..00000000
--- a/vendor/github.com/muesli/termenv/ansi_compat.md
+++ /dev/null
@@ -1,65 +0,0 @@
-## Change Foreground Color
-
-This command should enable a blue foreground color:
-
-```bash
-echo -ne "\033]10;#0000ff\007"
-```
-
-## Change Background Color
-
-This command should enable a green background color:
-
-```bash
-echo -ne "\033]11;#00ff00\007"
-```
-
-## Change Cursor Color
-
-This command should enable a red cursor color:
-
-```bash
-echo -ne "\033]12;#ff0000\007"
-```
-
-## Query Color Scheme
-
-These two commands should print out the currently active color scheme:
-
-```bash
-echo -ne "\033]10;?\033\\"
-echo -ne "\033]11;?\033\\"
-```
-
-## Query Cursor Position
-
-This command should print out the current cursor position:
-
-```bash
-echo -ne "\033[6n"
-```
-
-## Set Window Title
-
-This command should set the window title to "Test":
-
-```bash
-echo -ne "\033]2;Test\007" && sleep 10
-```
-
-## Bracketed paste
-
-Enter this command, then paste a word from the clipboard. The text
-displayed on the terminal should contain the codes `200~` and `201~`:
-
-```bash
-echo -ne "\033[?2004h" && sleep 10
-```
-
-## Trigger Notification
-
-This command should trigger a notification:
-
-```bash
-echo -ne "\033]777;notify;Title;Body\033\\"
-```
diff --git a/vendor/github.com/muesli/termenv/ansicolors.go b/vendor/github.com/muesli/termenv/ansicolors.go
deleted file mode 100644
index 1a301b0f..00000000
--- a/vendor/github.com/muesli/termenv/ansicolors.go
+++ /dev/null
@@ -1,281 +0,0 @@
-package termenv
-
-// ANSI color codes.
-const (
- ANSIBlack ANSIColor = iota
- ANSIRed
- ANSIGreen
- ANSIYellow
- ANSIBlue
- ANSIMagenta
- ANSICyan
- ANSIWhite
- ANSIBrightBlack
- ANSIBrightRed
- ANSIBrightGreen
- ANSIBrightYellow
- ANSIBrightBlue
- ANSIBrightMagenta
- ANSIBrightCyan
- ANSIBrightWhite
-)
-
-// RGB values of ANSI colors (0-255).
-var ansiHex = []string{
- "#000000",
- "#800000",
- "#008000",
- "#808000",
- "#000080",
- "#800080",
- "#008080",
- "#c0c0c0",
- "#808080",
- "#ff0000",
- "#00ff00",
- "#ffff00",
- "#0000ff",
- "#ff00ff",
- "#00ffff",
- "#ffffff",
- "#000000",
- "#00005f",
- "#000087",
- "#0000af",
- "#0000d7",
- "#0000ff",
- "#005f00",
- "#005f5f",
- "#005f87",
- "#005faf",
- "#005fd7",
- "#005fff",
- "#008700",
- "#00875f",
- "#008787",
- "#0087af",
- "#0087d7",
- "#0087ff",
- "#00af00",
- "#00af5f",
- "#00af87",
- "#00afaf",
- "#00afd7",
- "#00afff",
- "#00d700",
- "#00d75f",
- "#00d787",
- "#00d7af",
- "#00d7d7",
- "#00d7ff",
- "#00ff00",
- "#00ff5f",
- "#00ff87",
- "#00ffaf",
- "#00ffd7",
- "#00ffff",
- "#5f0000",
- "#5f005f",
- "#5f0087",
- "#5f00af",
- "#5f00d7",
- "#5f00ff",
- "#5f5f00",
- "#5f5f5f",
- "#5f5f87",
- "#5f5faf",
- "#5f5fd7",
- "#5f5fff",
- "#5f8700",
- "#5f875f",
- "#5f8787",
- "#5f87af",
- "#5f87d7",
- "#5f87ff",
- "#5faf00",
- "#5faf5f",
- "#5faf87",
- "#5fafaf",
- "#5fafd7",
- "#5fafff",
- "#5fd700",
- "#5fd75f",
- "#5fd787",
- "#5fd7af",
- "#5fd7d7",
- "#5fd7ff",
- "#5fff00",
- "#5fff5f",
- "#5fff87",
- "#5fffaf",
- "#5fffd7",
- "#5fffff",
- "#870000",
- "#87005f",
- "#870087",
- "#8700af",
- "#8700d7",
- "#8700ff",
- "#875f00",
- "#875f5f",
- "#875f87",
- "#875faf",
- "#875fd7",
- "#875fff",
- "#878700",
- "#87875f",
- "#878787",
- "#8787af",
- "#8787d7",
- "#8787ff",
- "#87af00",
- "#87af5f",
- "#87af87",
- "#87afaf",
- "#87afd7",
- "#87afff",
- "#87d700",
- "#87d75f",
- "#87d787",
- "#87d7af",
- "#87d7d7",
- "#87d7ff",
- "#87ff00",
- "#87ff5f",
- "#87ff87",
- "#87ffaf",
- "#87ffd7",
- "#87ffff",
- "#af0000",
- "#af005f",
- "#af0087",
- "#af00af",
- "#af00d7",
- "#af00ff",
- "#af5f00",
- "#af5f5f",
- "#af5f87",
- "#af5faf",
- "#af5fd7",
- "#af5fff",
- "#af8700",
- "#af875f",
- "#af8787",
- "#af87af",
- "#af87d7",
- "#af87ff",
- "#afaf00",
- "#afaf5f",
- "#afaf87",
- "#afafaf",
- "#afafd7",
- "#afafff",
- "#afd700",
- "#afd75f",
- "#afd787",
- "#afd7af",
- "#afd7d7",
- "#afd7ff",
- "#afff00",
- "#afff5f",
- "#afff87",
- "#afffaf",
- "#afffd7",
- "#afffff",
- "#d70000",
- "#d7005f",
- "#d70087",
- "#d700af",
- "#d700d7",
- "#d700ff",
- "#d75f00",
- "#d75f5f",
- "#d75f87",
- "#d75faf",
- "#d75fd7",
- "#d75fff",
- "#d78700",
- "#d7875f",
- "#d78787",
- "#d787af",
- "#d787d7",
- "#d787ff",
- "#d7af00",
- "#d7af5f",
- "#d7af87",
- "#d7afaf",
- "#d7afd7",
- "#d7afff",
- "#d7d700",
- "#d7d75f",
- "#d7d787",
- "#d7d7af",
- "#d7d7d7",
- "#d7d7ff",
- "#d7ff00",
- "#d7ff5f",
- "#d7ff87",
- "#d7ffaf",
- "#d7ffd7",
- "#d7ffff",
- "#ff0000",
- "#ff005f",
- "#ff0087",
- "#ff00af",
- "#ff00d7",
- "#ff00ff",
- "#ff5f00",
- "#ff5f5f",
- "#ff5f87",
- "#ff5faf",
- "#ff5fd7",
- "#ff5fff",
- "#ff8700",
- "#ff875f",
- "#ff8787",
- "#ff87af",
- "#ff87d7",
- "#ff87ff",
- "#ffaf00",
- "#ffaf5f",
- "#ffaf87",
- "#ffafaf",
- "#ffafd7",
- "#ffafff",
- "#ffd700",
- "#ffd75f",
- "#ffd787",
- "#ffd7af",
- "#ffd7d7",
- "#ffd7ff",
- "#ffff00",
- "#ffff5f",
- "#ffff87",
- "#ffffaf",
- "#ffffd7",
- "#ffffff",
- "#080808",
- "#121212",
- "#1c1c1c",
- "#262626",
- "#303030",
- "#3a3a3a",
- "#444444",
- "#4e4e4e",
- "#585858",
- "#626262",
- "#6c6c6c",
- "#767676",
- "#808080",
- "#8a8a8a",
- "#949494",
- "#9e9e9e",
- "#a8a8a8",
- "#b2b2b2",
- "#bcbcbc",
- "#c6c6c6",
- "#d0d0d0",
- "#dadada",
- "#e4e4e4",
- "#eeeeee",
-}
diff --git a/vendor/github.com/muesli/termenv/color.go b/vendor/github.com/muesli/termenv/color.go
deleted file mode 100644
index 59e639b1..00000000
--- a/vendor/github.com/muesli/termenv/color.go
+++ /dev/null
@@ -1,205 +0,0 @@
-package termenv
-
-import (
- "errors"
- "fmt"
- "math"
- "strings"
-
- "github.com/lucasb-eyer/go-colorful"
-)
-
-// ErrInvalidColor gets returned when a color is invalid.
-var ErrInvalidColor = errors.New("invalid color")
-
-// Foreground and Background sequence codes.
-const (
- Foreground = "38"
- Background = "48"
-)
-
-// Color is an interface implemented by all colors that can be converted to an
-// ANSI sequence.
-type Color interface {
- // Sequence returns the ANSI Sequence for the color.
- Sequence(bg bool) string
-}
-
-// NoColor is a nop for terminals that don't support colors.
-type NoColor struct{}
-
-func (c NoColor) String() string {
- return ""
-}
-
-// ANSIColor is a color (0-15) as defined by the ANSI Standard.
-type ANSIColor int
-
-func (c ANSIColor) String() string {
- return ansiHex[c]
-}
-
-// ANSI256Color is a color (16-255) as defined by the ANSI Standard.
-type ANSI256Color int
-
-func (c ANSI256Color) String() string {
- return ansiHex[c]
-}
-
-// RGBColor is a hex-encoded color, e.g. "#abcdef".
-type RGBColor string
-
-// ConvertToRGB converts a Color to a colorful.Color.
-func ConvertToRGB(c Color) colorful.Color {
- var hex string
- switch v := c.(type) {
- case RGBColor:
- hex = string(v)
- case ANSIColor:
- hex = ansiHex[v]
- case ANSI256Color:
- hex = ansiHex[v]
- }
-
- ch, _ := colorful.Hex(hex)
- return ch
-}
-
-// Sequence returns the ANSI Sequence for the color.
-func (c NoColor) Sequence(_ bool) string {
- return ""
-}
-
-// Sequence returns the ANSI Sequence for the color.
-//
-//nolint:mnd
-func (c ANSIColor) Sequence(bg bool) string {
- col := int(c)
- bgMod := func(c int) int {
- if bg {
- return c + 10
- }
- return c
- }
-
- if col < 8 {
- return fmt.Sprintf("%d", bgMod(col)+30) //nolint:mnd
- }
- return fmt.Sprintf("%d", bgMod(col-8)+90) //nolint:mnd
-}
-
-// Sequence returns the ANSI Sequence for the color.
-func (c ANSI256Color) Sequence(bg bool) string {
- prefix := Foreground
- if bg {
- prefix = Background
- }
- return fmt.Sprintf("%s;5;%d", prefix, c)
-}
-
-// Sequence returns the ANSI Sequence for the color.
-func (c RGBColor) Sequence(bg bool) string {
- f, err := colorful.Hex(string(c))
- if err != nil {
- return ""
- }
-
- prefix := Foreground
- if bg {
- prefix = Background
- }
- return fmt.Sprintf("%s;2;%d;%d;%d", prefix, uint8(f.R*255), uint8(f.G*255), uint8(f.B*255)) //nolint:mnd
-}
-
-func xTermColor(s string) (RGBColor, error) {
- if len(s) < 24 || len(s) > 25 {
- return RGBColor(""), ErrInvalidColor
- }
-
- switch {
- case strings.HasSuffix(s, string(BEL)):
- s = strings.TrimSuffix(s, string(BEL))
- case strings.HasSuffix(s, string(ESC)):
- s = strings.TrimSuffix(s, string(ESC))
- case strings.HasSuffix(s, ST):
- s = strings.TrimSuffix(s, ST)
- default:
- return RGBColor(""), ErrInvalidColor
- }
-
- s = s[4:]
-
- prefix := ";rgb:"
- if !strings.HasPrefix(s, prefix) {
- return RGBColor(""), ErrInvalidColor
- }
- s = strings.TrimPrefix(s, prefix)
-
- h := strings.Split(s, "/")
- hex := fmt.Sprintf("#%s%s%s", h[0][:2], h[1][:2], h[2][:2])
- return RGBColor(hex), nil
-}
-
-func ansi256ToANSIColor(c ANSI256Color) ANSIColor {
- var r int
- md := math.MaxFloat64
-
- h, _ := colorful.Hex(ansiHex[c])
- for i := 0; i <= 15; i++ {
- hb, _ := colorful.Hex(ansiHex[i])
- d := h.DistanceHSLuv(hb)
-
- if d < md {
- md = d
- r = i
- }
- }
-
- return ANSIColor(r)
-}
-
-//nolint:mnd
-func hexToANSI256Color(c colorful.Color) ANSI256Color {
- v2ci := func(v float64) int {
- if v < 48 {
- return 0
- }
- if v < 115 {
- return 1
- }
- return int((v - 35) / 40)
- }
-
- // Calculate the nearest 0-based color index at 16..231
- r := v2ci(c.R * 255.0) // 0..5 each
- g := v2ci(c.G * 255.0)
- b := v2ci(c.B * 255.0)
- ci := 36*r + 6*g + b /* 0..215 */
-
- // Calculate the represented colors back from the index
- i2cv := [6]int{0, 0x5f, 0x87, 0xaf, 0xd7, 0xff}
- cr := i2cv[r] // r/g/b, 0..255 each
- cg := i2cv[g]
- cb := i2cv[b]
-
- // Calculate the nearest 0-based gray index at 232..255
- var grayIdx int
- average := (r + g + b) / 3
- if average > 238 {
- grayIdx = 23
- } else {
- grayIdx = (average - 3) / 10 // 0..23
- }
- gv := 8 + 10*grayIdx // same value for r/g/b, 0..255
-
- // Return the one which is nearer to the original input rgb value
- c2 := colorful.Color{R: float64(cr) / 255.0, G: float64(cg) / 255.0, B: float64(cb) / 255.0}
- g2 := colorful.Color{R: float64(gv) / 255.0, G: float64(gv) / 255.0, B: float64(gv) / 255.0}
- colorDist := c.DistanceHSLuv(c2)
- grayDist := c.DistanceHSLuv(g2)
-
- if colorDist <= grayDist {
- return ANSI256Color(16 + ci)
- }
- return ANSI256Color(232 + grayIdx)
-}
diff --git a/vendor/github.com/muesli/termenv/constants_linux.go b/vendor/github.com/muesli/termenv/constants_linux.go
deleted file mode 100644
index 4262f03b..00000000
--- a/vendor/github.com/muesli/termenv/constants_linux.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package termenv
-
-import "golang.org/x/sys/unix"
-
-const (
- tcgetattr = unix.TCGETS
- tcsetattr = unix.TCSETS
-)
diff --git a/vendor/github.com/muesli/termenv/constants_solaris.go b/vendor/github.com/muesli/termenv/constants_solaris.go
deleted file mode 100644
index 4262f03b..00000000
--- a/vendor/github.com/muesli/termenv/constants_solaris.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package termenv
-
-import "golang.org/x/sys/unix"
-
-const (
- tcgetattr = unix.TCGETS
- tcsetattr = unix.TCSETS
-)
diff --git a/vendor/github.com/muesli/termenv/constants_unix.go b/vendor/github.com/muesli/termenv/constants_unix.go
deleted file mode 100644
index 5d664245..00000000
--- a/vendor/github.com/muesli/termenv/constants_unix.go
+++ /dev/null
@@ -1,13 +0,0 @@
-//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && !solaris && !illumos
-// +build darwin dragonfly freebsd netbsd openbsd
-// +build !solaris
-// +build !illumos
-
-package termenv
-
-import "golang.org/x/sys/unix"
-
-const (
- tcgetattr = unix.TIOCGETA
- tcsetattr = unix.TIOCSETA
-)
diff --git a/vendor/github.com/muesli/termenv/constants_zos.go b/vendor/github.com/muesli/termenv/constants_zos.go
deleted file mode 100644
index 4262f03b..00000000
--- a/vendor/github.com/muesli/termenv/constants_zos.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package termenv
-
-import "golang.org/x/sys/unix"
-
-const (
- tcgetattr = unix.TCGETS
- tcsetattr = unix.TCSETS
-)
diff --git a/vendor/github.com/muesli/termenv/copy.go b/vendor/github.com/muesli/termenv/copy.go
deleted file mode 100644
index 4bf5c9fe..00000000
--- a/vendor/github.com/muesli/termenv/copy.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package termenv
-
-import (
- "strings"
-
- "github.com/aymanbagabas/go-osc52/v2"
-)
-
-// Copy copies text to clipboard using OSC 52 escape sequence.
-func (o Output) Copy(str string) {
- s := osc52.New(str)
- if strings.HasPrefix(o.environ.Getenv("TERM"), "screen") {
- s = s.Screen()
- }
- _, _ = s.WriteTo(o)
-}
-
-// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape
-// sequence.
-func (o Output) CopyPrimary(str string) {
- s := osc52.New(str).Primary()
- if strings.HasPrefix(o.environ.Getenv("TERM"), "screen") {
- s = s.Screen()
- }
- _, _ = s.WriteTo(o)
-}
-
-// Copy copies text to clipboard using OSC 52 escape sequence.
-func Copy(str string) {
- output.Copy(str)
-}
-
-// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape
-// sequence.
-func CopyPrimary(str string) {
- output.CopyPrimary(str)
-}
diff --git a/vendor/github.com/muesli/termenv/hyperlink.go b/vendor/github.com/muesli/termenv/hyperlink.go
deleted file mode 100644
index 97e760a3..00000000
--- a/vendor/github.com/muesli/termenv/hyperlink.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package termenv
-
-// Hyperlink creates a hyperlink using OSC8.
-func Hyperlink(link, name string) string {
- return output.Hyperlink(link, name)
-}
-
-// Hyperlink creates a hyperlink using OSC8.
-func (o *Output) Hyperlink(link, name string) string {
- return OSC + "8;;" + link + ST + name + OSC + "8;;" + ST
-}
diff --git a/vendor/github.com/muesli/termenv/notification.go b/vendor/github.com/muesli/termenv/notification.go
deleted file mode 100644
index 2a8cf06a..00000000
--- a/vendor/github.com/muesli/termenv/notification.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package termenv
-
-// Notify triggers a notification using OSC777.
-func Notify(title, body string) {
- output.Notify(title, body)
-}
-
-// Notify triggers a notification using OSC777.
-func (o *Output) Notify(title, body string) {
- _, _ = o.WriteString(OSC + "777;notify;" + title + ";" + body + ST)
-}
diff --git a/vendor/github.com/muesli/termenv/output.go b/vendor/github.com/muesli/termenv/output.go
deleted file mode 100644
index e4434de0..00000000
--- a/vendor/github.com/muesli/termenv/output.go
+++ /dev/null
@@ -1,205 +0,0 @@
-package termenv
-
-import (
- "io"
- "os"
- "sync"
-)
-
-// output is the default global output.
-var output = NewOutput(os.Stdout)
-
-// File represents a file descriptor.
-//
-// Deprecated: Use *os.File instead.
-type File interface {
- io.ReadWriter
- Fd() uintptr
-}
-
-// OutputOption sets an option on Output.
-type OutputOption = func(*Output)
-
-// Output is a terminal output.
-type Output struct {
- Profile
- w io.Writer
- environ Environ
-
- assumeTTY bool
- unsafe bool
- cache bool
- fgSync *sync.Once
- fgColor Color
- bgSync *sync.Once
- bgColor Color
-}
-
-// Environ is an interface for getting environment variables.
-type Environ interface {
- Environ() []string
- Getenv(string) string
-}
-
-type osEnviron struct{}
-
-func (oe *osEnviron) Environ() []string {
- return os.Environ()
-}
-
-func (oe *osEnviron) Getenv(key string) string {
- return os.Getenv(key)
-}
-
-// DefaultOutput returns the default global output.
-func DefaultOutput() *Output {
- return output
-}
-
-// SetDefaultOutput sets the default global output.
-func SetDefaultOutput(o *Output) {
- output = o
-}
-
-// NewOutput returns a new Output for the given writer.
-func NewOutput(w io.Writer, opts ...OutputOption) *Output {
- o := &Output{
- w: w,
- environ: &osEnviron{},
- Profile: -1,
- fgSync: &sync.Once{},
- fgColor: NoColor{},
- bgSync: &sync.Once{},
- bgColor: NoColor{},
- }
-
- if o.w == nil {
- o.w = os.Stdout
- }
- for _, opt := range opts {
- opt(o)
- }
- if o.Profile < 0 {
- o.Profile = o.EnvColorProfile()
- }
-
- return o
-}
-
-// WithEnvironment returns a new OutputOption for the given environment.
-func WithEnvironment(environ Environ) OutputOption {
- return func(o *Output) {
- o.environ = environ
- }
-}
-
-// WithProfile returns a new OutputOption for the given profile.
-func WithProfile(profile Profile) OutputOption {
- return func(o *Output) {
- o.Profile = profile
- }
-}
-
-// WithColorCache returns a new OutputOption with fore- and background color values
-// pre-fetched and cached.
-func WithColorCache(v bool) OutputOption {
- return func(o *Output) {
- o.cache = v
-
- // cache the values now
- _ = o.ForegroundColor()
- _ = o.BackgroundColor()
- }
-}
-
-// WithTTY returns a new OutputOption to assume whether or not the output is a TTY.
-// This is useful when mocking console output.
-func WithTTY(v bool) OutputOption {
- return func(o *Output) {
- o.assumeTTY = v
- }
-}
-
-// WithUnsafe returns a new OutputOption with unsafe mode enabled. Unsafe mode doesn't
-// check whether or not the terminal is a TTY.
-//
-// This option supersedes WithTTY.
-//
-// This is useful when mocking console output and enforcing ANSI escape output
-// e.g. on SSH sessions.
-func WithUnsafe() OutputOption {
- return func(o *Output) {
- o.unsafe = true
- }
-}
-
-// ForegroundColor returns the terminal's default foreground color.
-func (o *Output) ForegroundColor() Color {
- f := func() {
- if !o.isTTY() {
- return
- }
-
- o.fgColor = o.foregroundColor()
- }
-
- if o.cache {
- o.fgSync.Do(f)
- } else {
- f()
- }
-
- return o.fgColor
-}
-
-// BackgroundColor returns the terminal's default background color.
-func (o *Output) BackgroundColor() Color {
- f := func() {
- if !o.isTTY() {
- return
- }
-
- o.bgColor = o.backgroundColor()
- }
-
- if o.cache {
- o.bgSync.Do(f)
- } else {
- f()
- }
-
- return o.bgColor
-}
-
-// HasDarkBackground returns whether terminal uses a dark-ish background.
-func (o *Output) HasDarkBackground() bool {
- c := ConvertToRGB(o.BackgroundColor())
- _, _, l := c.Hsl()
- return l < 0.5 //nolint:mnd
-}
-
-// TTY returns the terminal's file descriptor. This may be nil if the output is
-// not a terminal.
-//
-// Deprecated: Use Writer() instead.
-func (o Output) TTY() File {
- if f, ok := o.w.(File); ok {
- return f
- }
- return nil
-}
-
-// Writer returns the underlying writer. This may be of type io.Writer,
-// io.ReadWriter, or *os.File.
-func (o Output) Writer() io.Writer {
- return o.w
-}
-
-func (o Output) Write(p []byte) (int, error) {
- return o.w.Write(p) //nolint:wrapcheck
-}
-
-// WriteString writes the given string to the output.
-func (o Output) WriteString(s string) (int, error) {
- return o.Write([]byte(s))
-}
diff --git a/vendor/github.com/muesli/termenv/profile.go b/vendor/github.com/muesli/termenv/profile.go
deleted file mode 100644
index 7d38f5fb..00000000
--- a/vendor/github.com/muesli/termenv/profile.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package termenv
-
-import (
- "image/color"
- "strconv"
- "strings"
-
- "github.com/lucasb-eyer/go-colorful"
-)
-
-// Profile is a color profile: Ascii, ANSI, ANSI256, or TrueColor.
-type Profile int
-
-const (
- // TrueColor, 24-bit color profile.
- TrueColor = Profile(iota)
- // ANSI256, 8-bit color profile.
- ANSI256
- // ANSI, 4-bit color profile.
- ANSI
- // Ascii, uncolored profile.
- Ascii //nolint:revive
-)
-
-// Name returns the profile name as a string.
-func (p Profile) Name() string {
- switch p {
- case Ascii:
- return "Ascii"
- case ANSI:
- return "ANSI"
- case ANSI256:
- return "ANSI256"
- case TrueColor:
- return "TrueColor"
- }
- return "Unknown"
-}
-
-// String returns a new Style.
-func (p Profile) String(s ...string) Style {
- return Style{
- profile: p,
- string: strings.Join(s, " "),
- }
-}
-
-// Convert transforms a given Color to a Color supported within the Profile.
-func (p Profile) Convert(c Color) Color {
- if p == Ascii {
- return NoColor{}
- }
-
- switch v := c.(type) {
- case ANSIColor:
- return v
-
- case ANSI256Color:
- if p == ANSI {
- return ansi256ToANSIColor(v)
- }
- return v
-
- case RGBColor:
- h, err := colorful.Hex(string(v))
- if err != nil {
- return nil
- }
- if p != TrueColor {
- ac := hexToANSI256Color(h)
- if p == ANSI {
- return ansi256ToANSIColor(ac)
- }
- return ac
- }
- return v
- }
-
- return c
-}
-
-// Color creates a Color from a string. Valid inputs are hex colors, as well as
-// ANSI color codes (0-15, 16-255).
-func (p Profile) Color(s string) Color {
- if len(s) == 0 {
- return nil
- }
-
- var c Color
- if strings.HasPrefix(s, "#") {
- c = RGBColor(s)
- } else {
- i, err := strconv.Atoi(s)
- if err != nil {
- return nil
- }
-
- if i < 16 { //nolint:mnd
- c = ANSIColor(i)
- } else {
- c = ANSI256Color(i)
- }
- }
-
- return p.Convert(c)
-}
-
-// FromColor creates a Color from a color.Color.
-func (p Profile) FromColor(c color.Color) Color {
- col, _ := colorful.MakeColor(c)
- return p.Color(col.Hex())
-}
diff --git a/vendor/github.com/muesli/termenv/screen.go b/vendor/github.com/muesli/termenv/screen.go
deleted file mode 100644
index 75c11d01..00000000
--- a/vendor/github.com/muesli/termenv/screen.go
+++ /dev/null
@@ -1,590 +0,0 @@
-package termenv
-
-import (
- "fmt"
- "strings"
-)
-
-// Sequence definitions.
-const (
- // Cursor positioning.
- CursorUpSeq = "%dA"
- CursorDownSeq = "%dB"
- CursorForwardSeq = "%dC"
- CursorBackSeq = "%dD"
- CursorNextLineSeq = "%dE"
- CursorPreviousLineSeq = "%dF"
- CursorHorizontalSeq = "%dG"
- CursorPositionSeq = "%d;%dH"
- EraseDisplaySeq = "%dJ"
- EraseLineSeq = "%dK"
- ScrollUpSeq = "%dS"
- ScrollDownSeq = "%dT"
- SaveCursorPositionSeq = "s"
- RestoreCursorPositionSeq = "u"
- ChangeScrollingRegionSeq = "%d;%dr"
- InsertLineSeq = "%dL"
- DeleteLineSeq = "%dM"
-
- // Explicit values for EraseLineSeq.
- EraseLineRightSeq = "0K"
- EraseLineLeftSeq = "1K"
- EraseEntireLineSeq = "2K"
-
- // Mouse.
- EnableMousePressSeq = "?9h" // press only (X10)
- DisableMousePressSeq = "?9l"
- EnableMouseSeq = "?1000h" // press, release, wheel
- DisableMouseSeq = "?1000l"
- EnableMouseHiliteSeq = "?1001h" // highlight
- DisableMouseHiliteSeq = "?1001l"
- EnableMouseCellMotionSeq = "?1002h" // press, release, move on pressed, wheel
- DisableMouseCellMotionSeq = "?1002l"
- EnableMouseAllMotionSeq = "?1003h" // press, release, move, wheel
- DisableMouseAllMotionSeq = "?1003l"
- EnableMouseExtendedModeSeq = "?1006h" // press, release, move, wheel, extended coordinates
- DisableMouseExtendedModeSeq = "?1006l"
- EnableMousePixelsModeSeq = "?1016h" // press, release, move, wheel, extended pixel coordinates
- DisableMousePixelsModeSeq = "?1016l"
-
- // Screen.
- RestoreScreenSeq = "?47l"
- SaveScreenSeq = "?47h"
- AltScreenSeq = "?1049h"
- ExitAltScreenSeq = "?1049l"
-
- // Bracketed paste.
- // https://en.wikipedia.org/wiki/Bracketed-paste
- EnableBracketedPasteSeq = "?2004h"
- DisableBracketedPasteSeq = "?2004l"
- StartBracketedPasteSeq = "200~"
- EndBracketedPasteSeq = "201~"
-
- // Session.
- SetWindowTitleSeq = "2;%s" + string(BEL)
- SetForegroundColorSeq = "10;%s" + string(BEL)
- SetBackgroundColorSeq = "11;%s" + string(BEL)
- SetCursorColorSeq = "12;%s" + string(BEL)
- ShowCursorSeq = "?25h"
- HideCursorSeq = "?25l"
-)
-
-// Reset the terminal to its default style, removing any active styles.
-func (o Output) Reset() {
- fmt.Fprint(o.w, CSI+ResetSeq+"m") //nolint:errcheck
-}
-
-// SetForegroundColor sets the default foreground color.
-func (o Output) SetForegroundColor(color Color) {
- fmt.Fprintf(o.w, OSC+SetForegroundColorSeq, color) //nolint:errcheck
-}
-
-// SetBackgroundColor sets the default background color.
-func (o Output) SetBackgroundColor(color Color) {
- fmt.Fprintf(o.w, OSC+SetBackgroundColorSeq, color) //nolint:errcheck
-}
-
-// SetCursorColor sets the cursor color.
-func (o Output) SetCursorColor(color Color) {
- fmt.Fprintf(o.w, OSC+SetCursorColorSeq, color) //nolint:errcheck
-}
-
-// RestoreScreen restores a previously saved screen state.
-func (o Output) RestoreScreen() {
- fmt.Fprint(o.w, CSI+RestoreScreenSeq) //nolint:errcheck
-}
-
-// SaveScreen saves the screen state.
-func (o Output) SaveScreen() {
- fmt.Fprint(o.w, CSI+SaveScreenSeq) //nolint:errcheck
-}
-
-// AltScreen switches to the alternate screen buffer. The former view can be
-// restored with ExitAltScreen().
-func (o Output) AltScreen() {
- fmt.Fprint(o.w, CSI+AltScreenSeq) //nolint:errcheck
-}
-
-// ExitAltScreen exits the alternate screen buffer and returns to the former
-// terminal view.
-func (o Output) ExitAltScreen() {
- fmt.Fprint(o.w, CSI+ExitAltScreenSeq) //nolint:errcheck
-}
-
-// ClearScreen clears the visible portion of the terminal.
-func (o Output) ClearScreen() {
- fmt.Fprintf(o.w, CSI+EraseDisplaySeq, 2) //nolint:errcheck,mnd
- o.MoveCursor(1, 1)
-}
-
-// MoveCursor moves the cursor to a given position.
-func (o Output) MoveCursor(row int, column int) {
- fmt.Fprintf(o.w, CSI+CursorPositionSeq, row, column) //nolint:errcheck
-}
-
-// HideCursor hides the cursor.
-func (o Output) HideCursor() {
- fmt.Fprint(o.w, CSI+HideCursorSeq) //nolint:errcheck
-}
-
-// ShowCursor shows the cursor.
-func (o Output) ShowCursor() {
- fmt.Fprint(o.w, CSI+ShowCursorSeq) //nolint:errcheck
-}
-
-// SaveCursorPosition saves the cursor position.
-func (o Output) SaveCursorPosition() {
- fmt.Fprint(o.w, CSI+SaveCursorPositionSeq) //nolint:errcheck
-}
-
-// RestoreCursorPosition restores a saved cursor position.
-func (o Output) RestoreCursorPosition() {
- fmt.Fprint(o.w, CSI+RestoreCursorPositionSeq) //nolint:errcheck
-}
-
-// CursorUp moves the cursor up a given number of lines.
-func (o Output) CursorUp(n int) {
- fmt.Fprintf(o.w, CSI+CursorUpSeq, n) //nolint:errcheck
-}
-
-// CursorDown moves the cursor down a given number of lines.
-func (o Output) CursorDown(n int) {
- fmt.Fprintf(o.w, CSI+CursorDownSeq, n) //nolint:errcheck
-}
-
-// CursorForward moves the cursor up a given number of lines.
-func (o Output) CursorForward(n int) {
- fmt.Fprintf(o.w, CSI+CursorForwardSeq, n) //nolint:errcheck
-}
-
-// CursorBack moves the cursor backwards a given number of cells.
-func (o Output) CursorBack(n int) {
- fmt.Fprintf(o.w, CSI+CursorBackSeq, n) //nolint:errcheck
-}
-
-// CursorNextLine moves the cursor down a given number of lines and places it at
-// the beginning of the line.
-func (o Output) CursorNextLine(n int) {
- fmt.Fprintf(o.w, CSI+CursorNextLineSeq, n) //nolint:errcheck
-}
-
-// CursorPrevLine moves the cursor up a given number of lines and places it at
-// the beginning of the line.
-func (o Output) CursorPrevLine(n int) {
- fmt.Fprintf(o.w, CSI+CursorPreviousLineSeq, n) //nolint:errcheck
-}
-
-// ClearLine clears the current line.
-func (o Output) ClearLine() {
- fmt.Fprint(o.w, CSI+EraseEntireLineSeq) //nolint:errcheck
-}
-
-// ClearLineLeft clears the line to the left of the cursor.
-func (o Output) ClearLineLeft() {
- fmt.Fprint(o.w, CSI+EraseLineLeftSeq) //nolint:errcheck
-}
-
-// ClearLineRight clears the line to the right of the cursor.
-func (o Output) ClearLineRight() {
- fmt.Fprint(o.w, CSI+EraseLineRightSeq) //nolint:errcheck
-}
-
-// ClearLines clears a given number of lines.
-func (o Output) ClearLines(n int) {
- clearLine := fmt.Sprintf(CSI+EraseLineSeq, 2) //nolint:mnd
- cursorUp := fmt.Sprintf(CSI+CursorUpSeq, 1)
- fmt.Fprint(o.w, clearLine+strings.Repeat(cursorUp+clearLine, n)) //nolint:errcheck
-}
-
-// ChangeScrollingRegion sets the scrolling region of the terminal.
-func (o Output) ChangeScrollingRegion(top, bottom int) {
- fmt.Fprintf(o.w, CSI+ChangeScrollingRegionSeq, top, bottom) //nolint:errcheck
-}
-
-// InsertLines inserts the given number of lines at the top of the scrollable
-// region, pushing lines below down.
-func (o Output) InsertLines(n int) {
- fmt.Fprintf(o.w, CSI+InsertLineSeq, n) //nolint:errcheck
-}
-
-// DeleteLines deletes the given number of lines, pulling any lines in
-// the scrollable region below up.
-func (o Output) DeleteLines(n int) {
- fmt.Fprintf(o.w, CSI+DeleteLineSeq, n) //nolint:errcheck
-}
-
-// EnableMousePress enables X10 mouse mode. Button press events are sent only.
-func (o Output) EnableMousePress() {
- fmt.Fprint(o.w, CSI+EnableMousePressSeq) //nolint:errcheck
-}
-
-// DisableMousePress disables X10 mouse mode.
-func (o Output) DisableMousePress() {
- fmt.Fprint(o.w, CSI+DisableMousePressSeq) //nolint:errcheck
-}
-
-// EnableMouse enables Mouse Tracking mode.
-func (o Output) EnableMouse() {
- fmt.Fprint(o.w, CSI+EnableMouseSeq) //nolint:errcheck
-}
-
-// DisableMouse disables Mouse Tracking mode.
-func (o Output) DisableMouse() {
- fmt.Fprint(o.w, CSI+DisableMouseSeq) //nolint:errcheck
-}
-
-// EnableMouseHilite enables Hilite Mouse Tracking mode.
-func (o Output) EnableMouseHilite() {
- fmt.Fprint(o.w, CSI+EnableMouseHiliteSeq) //nolint:errcheck
-}
-
-// DisableMouseHilite disables Hilite Mouse Tracking mode.
-func (o Output) DisableMouseHilite() {
- fmt.Fprint(o.w, CSI+DisableMouseHiliteSeq) //nolint:errcheck
-}
-
-// EnableMouseCellMotion enables Cell Motion Mouse Tracking mode.
-func (o Output) EnableMouseCellMotion() {
- fmt.Fprint(o.w, CSI+EnableMouseCellMotionSeq) //nolint:errcheck
-}
-
-// DisableMouseCellMotion disables Cell Motion Mouse Tracking mode.
-func (o Output) DisableMouseCellMotion() {
- fmt.Fprint(o.w, CSI+DisableMouseCellMotionSeq) //nolint:errcheck
-}
-
-// EnableMouseAllMotion enables All Motion Mouse mode.
-func (o Output) EnableMouseAllMotion() {
- fmt.Fprint(o.w, CSI+EnableMouseAllMotionSeq) //nolint:errcheck
-}
-
-// DisableMouseAllMotion disables All Motion Mouse mode.
-func (o Output) DisableMouseAllMotion() {
- fmt.Fprint(o.w, CSI+DisableMouseAllMotionSeq) //nolint:errcheck
-}
-
-// EnableMouseExtendedMotion enables Extended Mouse mode (SGR). This should be
-// enabled in conjunction with EnableMouseCellMotion, and EnableMouseAllMotion.
-func (o Output) EnableMouseExtendedMode() {
- fmt.Fprint(o.w, CSI+EnableMouseExtendedModeSeq) //nolint:errcheck
-}
-
-// DisableMouseExtendedMotion disables Extended Mouse mode (SGR).
-func (o Output) DisableMouseExtendedMode() {
- fmt.Fprint(o.w, CSI+DisableMouseExtendedModeSeq) //nolint:errcheck
-}
-
-// EnableMousePixelsMotion enables Pixel Motion Mouse mode (SGR-Pixels). This
-// should be enabled in conjunction with EnableMouseCellMotion, and
-// EnableMouseAllMotion.
-func (o Output) EnableMousePixelsMode() {
- fmt.Fprint(o.w, CSI+EnableMousePixelsModeSeq) //nolint:errcheck
-}
-
-// DisableMousePixelsMotion disables Pixel Motion Mouse mode (SGR-Pixels).
-func (o Output) DisableMousePixelsMode() {
- fmt.Fprint(o.w, CSI+DisableMousePixelsModeSeq) //nolint:errcheck
-}
-
-// SetWindowTitle sets the terminal window title.
-func (o Output) SetWindowTitle(title string) {
- fmt.Fprintf(o.w, OSC+SetWindowTitleSeq, title) //nolint:errcheck
-}
-
-// EnableBracketedPaste enables bracketed paste.
-func (o Output) EnableBracketedPaste() {
- fmt.Fprintf(o.w, CSI+EnableBracketedPasteSeq) //nolint:errcheck
-}
-
-// DisableBracketedPaste disables bracketed paste.
-func (o Output) DisableBracketedPaste() {
- fmt.Fprintf(o.w, CSI+DisableBracketedPasteSeq) //nolint:errcheck
-}
-
-// Legacy functions.
-
-// Reset the terminal to its default style, removing any active styles.
-//
-// Deprecated: please use termenv.Output instead.
-func Reset() {
- output.Reset()
-}
-
-// SetForegroundColor sets the default foreground color.
-//
-// Deprecated: please use termenv.Output instead.
-func SetForegroundColor(color Color) {
- output.SetForegroundColor(color)
-}
-
-// SetBackgroundColor sets the default background color.
-//
-// Deprecated: please use termenv.Output instead.
-func SetBackgroundColor(color Color) {
- output.SetBackgroundColor(color)
-}
-
-// SetCursorColor sets the cursor color.
-//
-// Deprecated: please use termenv.Output instead.
-func SetCursorColor(color Color) {
- output.SetCursorColor(color)
-}
-
-// RestoreScreen restores a previously saved screen state.
-//
-// Deprecated: please use termenv.Output instead.
-func RestoreScreen() {
- output.RestoreScreen()
-}
-
-// SaveScreen saves the screen state.
-//
-// Deprecated: please use termenv.Output instead.
-func SaveScreen() {
- output.SaveScreen()
-}
-
-// AltScreen switches to the alternate screen buffer. The former view can be
-// restored with ExitAltScreen().
-//
-// Deprecated: please use termenv.Output instead.
-func AltScreen() {
- output.AltScreen()
-}
-
-// ExitAltScreen exits the alternate screen buffer and returns to the former
-// terminal view.
-//
-// Deprecated: please use termenv.Output instead.
-func ExitAltScreen() {
- output.ExitAltScreen()
-}
-
-// ClearScreen clears the visible portion of the terminal.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearScreen() {
- output.ClearScreen()
-}
-
-// MoveCursor moves the cursor to a given position.
-//
-// Deprecated: please use termenv.Output instead.
-func MoveCursor(row int, column int) {
- output.MoveCursor(row, column)
-}
-
-// HideCursor hides the cursor.
-//
-// Deprecated: please use termenv.Output instead.
-func HideCursor() {
- output.HideCursor()
-}
-
-// ShowCursor shows the cursor.
-//
-// Deprecated: please use termenv.Output instead.
-func ShowCursor() {
- output.ShowCursor()
-}
-
-// SaveCursorPosition saves the cursor position.
-//
-// Deprecated: please use termenv.Output instead.
-func SaveCursorPosition() {
- output.SaveCursorPosition()
-}
-
-// RestoreCursorPosition restores a saved cursor position.
-//
-// Deprecated: please use termenv.Output instead.
-func RestoreCursorPosition() {
- output.RestoreCursorPosition()
-}
-
-// CursorUp moves the cursor up a given number of lines.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorUp(n int) {
- output.CursorUp(n)
-}
-
-// CursorDown moves the cursor down a given number of lines.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorDown(n int) {
- output.CursorDown(n)
-}
-
-// CursorForward moves the cursor up a given number of lines.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorForward(n int) {
- output.CursorForward(n)
-}
-
-// CursorBack moves the cursor backwards a given number of cells.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorBack(n int) {
- output.CursorBack(n)
-}
-
-// CursorNextLine moves the cursor down a given number of lines and places it at
-// the beginning of the line.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorNextLine(n int) {
- output.CursorNextLine(n)
-}
-
-// CursorPrevLine moves the cursor up a given number of lines and places it at
-// the beginning of the line.
-//
-// Deprecated: please use termenv.Output instead.
-func CursorPrevLine(n int) {
- output.CursorPrevLine(n)
-}
-
-// ClearLine clears the current line.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearLine() {
- output.ClearLine()
-}
-
-// ClearLineLeft clears the line to the left of the cursor.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearLineLeft() {
- output.ClearLineLeft()
-}
-
-// ClearLineRight clears the line to the right of the cursor.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearLineRight() {
- output.ClearLineRight()
-}
-
-// ClearLines clears a given number of lines.
-//
-// Deprecated: please use termenv.Output instead.
-func ClearLines(n int) {
- output.ClearLines(n)
-}
-
-// ChangeScrollingRegion sets the scrolling region of the terminal.
-//
-// Deprecated: please use termenv.Output instead.
-func ChangeScrollingRegion(top, bottom int) {
- output.ChangeScrollingRegion(top, bottom)
-}
-
-// InsertLines inserts the given number of lines at the top of the scrollable
-// region, pushing lines below down.
-//
-// Deprecated: please use termenv.Output instead.
-func InsertLines(n int) {
- output.InsertLines(n)
-}
-
-// DeleteLines deletes the given number of lines, pulling any lines in
-// the scrollable region below up.
-//
-// Deprecated: please use termenv.Output instead.
-func DeleteLines(n int) {
- output.DeleteLines(n)
-}
-
-// EnableMousePress enables X10 mouse mode. Button press events are sent only.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMousePress() {
- output.EnableMousePress()
-}
-
-// DisableMousePress disables X10 mouse mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMousePress() {
- output.DisableMousePress()
-}
-
-// EnableMouse enables Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMouse() {
- output.EnableMouse()
-}
-
-// DisableMouse disables Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMouse() {
- output.DisableMouse()
-}
-
-// EnableMouseHilite enables Hilite Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMouseHilite() {
- output.EnableMouseHilite()
-}
-
-// DisableMouseHilite disables Hilite Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMouseHilite() {
- output.DisableMouseHilite()
-}
-
-// EnableMouseCellMotion enables Cell Motion Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMouseCellMotion() {
- output.EnableMouseCellMotion()
-}
-
-// DisableMouseCellMotion disables Cell Motion Mouse Tracking mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMouseCellMotion() {
- output.DisableMouseCellMotion()
-}
-
-// EnableMouseAllMotion enables All Motion Mouse mode.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableMouseAllMotion() {
- output.EnableMouseAllMotion()
-}
-
-// DisableMouseAllMotion disables All Motion Mouse mode.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableMouseAllMotion() {
- output.DisableMouseAllMotion()
-}
-
-// SetWindowTitle sets the terminal window title.
-//
-// Deprecated: please use termenv.Output instead.
-func SetWindowTitle(title string) {
- output.SetWindowTitle(title)
-}
-
-// EnableBracketedPaste enables bracketed paste.
-//
-// Deprecated: please use termenv.Output instead.
-func EnableBracketedPaste() {
- output.EnableBracketedPaste()
-}
-
-// DisableBracketedPaste disables bracketed paste.
-//
-// Deprecated: please use termenv.Output instead.
-func DisableBracketedPaste() {
- output.DisableBracketedPaste()
-}
diff --git a/vendor/github.com/muesli/termenv/style.go b/vendor/github.com/muesli/termenv/style.go
deleted file mode 100644
index dedc1f9f..00000000
--- a/vendor/github.com/muesli/termenv/style.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package termenv
-
-import (
- "fmt"
- "strings"
-
- "github.com/rivo/uniseg"
-)
-
-// Sequence definitions.
-const (
- ResetSeq = "0"
- BoldSeq = "1"
- FaintSeq = "2"
- ItalicSeq = "3"
- UnderlineSeq = "4"
- BlinkSeq = "5"
- ReverseSeq = "7"
- CrossOutSeq = "9"
- OverlineSeq = "53"
-)
-
-// Style is a string that various rendering styles can be applied to.
-type Style struct {
- profile Profile
- string
- styles []string
-}
-
-// String returns a new Style.
-func String(s ...string) Style {
- return Style{
- profile: ANSI,
- string: strings.Join(s, " "),
- }
-}
-
-func (t Style) String() string {
- return t.Styled(t.string)
-}
-
-// Styled renders s with all applied styles.
-func (t Style) Styled(s string) string {
- if t.profile == Ascii {
- return s
- }
- if len(t.styles) == 0 {
- return s
- }
-
- seq := strings.Join(t.styles, ";")
- if seq == "" {
- return s
- }
-
- return fmt.Sprintf("%s%sm%s%sm", CSI, seq, s, CSI+ResetSeq)
-}
-
-// Foreground sets a foreground color.
-func (t Style) Foreground(c Color) Style {
- if c != nil {
- t.styles = append(t.styles, c.Sequence(false))
- }
- return t
-}
-
-// Background sets a background color.
-func (t Style) Background(c Color) Style {
- if c != nil {
- t.styles = append(t.styles, c.Sequence(true))
- }
- return t
-}
-
-// Bold enables bold rendering.
-func (t Style) Bold() Style {
- t.styles = append(t.styles, BoldSeq)
- return t
-}
-
-// Faint enables faint rendering.
-func (t Style) Faint() Style {
- t.styles = append(t.styles, FaintSeq)
- return t
-}
-
-// Italic enables italic rendering.
-func (t Style) Italic() Style {
- t.styles = append(t.styles, ItalicSeq)
- return t
-}
-
-// Underline enables underline rendering.
-func (t Style) Underline() Style {
- t.styles = append(t.styles, UnderlineSeq)
- return t
-}
-
-// Overline enables overline rendering.
-func (t Style) Overline() Style {
- t.styles = append(t.styles, OverlineSeq)
- return t
-}
-
-// Blink enables blink mode.
-func (t Style) Blink() Style {
- t.styles = append(t.styles, BlinkSeq)
- return t
-}
-
-// Reverse enables reverse color mode.
-func (t Style) Reverse() Style {
- t.styles = append(t.styles, ReverseSeq)
- return t
-}
-
-// CrossOut enables crossed-out rendering.
-func (t Style) CrossOut() Style {
- t.styles = append(t.styles, CrossOutSeq)
- return t
-}
-
-// Width returns the width required to print all runes in Style.
-func (t Style) Width() int {
- return uniseg.StringWidth(t.string)
-}
diff --git a/vendor/github.com/muesli/termenv/templatehelper.go b/vendor/github.com/muesli/termenv/templatehelper.go
deleted file mode 100644
index 4c7c80f5..00000000
--- a/vendor/github.com/muesli/termenv/templatehelper.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package termenv
-
-import (
- "text/template"
-)
-
-// TemplateFuncs returns template helpers for the given output.
-func (o Output) TemplateFuncs() template.FuncMap {
- return TemplateFuncs(o.Profile)
-}
-
-// TemplateFuncs contains a few useful template helpers.
-//
-//nolint:mnd
-func TemplateFuncs(p Profile) template.FuncMap {
- if p == Ascii {
- return noopTemplateFuncs
- }
-
- return template.FuncMap{
- "Color": func(values ...interface{}) string {
- s := p.String(values[len(values)-1].(string))
- switch len(values) {
- case 2:
- s = s.Foreground(p.Color(values[0].(string)))
- case 3:
- s = s.
- Foreground(p.Color(values[0].(string))).
- Background(p.Color(values[1].(string)))
- }
-
- return s.String()
- },
- "Foreground": func(values ...interface{}) string {
- s := p.String(values[len(values)-1].(string))
- if len(values) == 2 {
- s = s.Foreground(p.Color(values[0].(string)))
- }
-
- return s.String()
- },
- "Background": func(values ...interface{}) string {
- s := p.String(values[len(values)-1].(string))
- if len(values) == 2 {
- s = s.Background(p.Color(values[0].(string)))
- }
-
- return s.String()
- },
- "Bold": styleFunc(p, Style.Bold),
- "Faint": styleFunc(p, Style.Faint),
- "Italic": styleFunc(p, Style.Italic),
- "Underline": styleFunc(p, Style.Underline),
- "Overline": styleFunc(p, Style.Overline),
- "Blink": styleFunc(p, Style.Blink),
- "Reverse": styleFunc(p, Style.Reverse),
- "CrossOut": styleFunc(p, Style.CrossOut),
- }
-}
-
-func styleFunc(p Profile, f func(Style) Style) func(...interface{}) string {
- return func(values ...interface{}) string {
- s := p.String(values[0].(string))
- return f(s).String()
- }
-}
-
-var noopTemplateFuncs = template.FuncMap{
- "Color": noColorFunc,
- "Foreground": noColorFunc,
- "Background": noColorFunc,
- "Bold": noStyleFunc,
- "Faint": noStyleFunc,
- "Italic": noStyleFunc,
- "Underline": noStyleFunc,
- "Overline": noStyleFunc,
- "Blink": noStyleFunc,
- "Reverse": noStyleFunc,
- "CrossOut": noStyleFunc,
-}
-
-func noColorFunc(values ...interface{}) string {
- return values[len(values)-1].(string)
-}
-
-func noStyleFunc(values ...interface{}) string {
- return values[0].(string)
-}
diff --git a/vendor/github.com/muesli/termenv/termenv.go b/vendor/github.com/muesli/termenv/termenv.go
deleted file mode 100644
index d702cd55..00000000
--- a/vendor/github.com/muesli/termenv/termenv.go
+++ /dev/null
@@ -1,115 +0,0 @@
-package termenv
-
-import (
- "errors"
- "os"
-
- "github.com/mattn/go-isatty"
-)
-
-var (
- // ErrStatusReport gets returned when the terminal can't be queried.
- ErrStatusReport = errors.New("unable to retrieve status report")
-)
-
-const (
- // Escape character.
- ESC = '\x1b'
- // Bell.
- BEL = '\a'
- // Control Sequence Introducer.
- CSI = string(ESC) + "["
- // Operating System Command.
- OSC = string(ESC) + "]"
- // String Terminator.
- ST = string(ESC) + `\`
-)
-
-func (o *Output) isTTY() bool {
- if o.assumeTTY || o.unsafe {
- return true
- }
- if len(o.environ.Getenv("CI")) > 0 {
- return false
- }
- if f, ok := o.Writer().(*os.File); ok {
- return isatty.IsTerminal(f.Fd())
- }
-
- return false
-}
-
-// ColorProfile returns the supported color profile:
-// Ascii, ANSI, ANSI256, or TrueColor.
-func ColorProfile() Profile {
- return output.ColorProfile()
-}
-
-// ForegroundColor returns the terminal's default foreground color.
-func ForegroundColor() Color {
- return output.ForegroundColor()
-}
-
-// BackgroundColor returns the terminal's default background color.
-func BackgroundColor() Color {
- return output.BackgroundColor()
-}
-
-// HasDarkBackground returns whether terminal uses a dark-ish background.
-func HasDarkBackground() bool {
- return output.HasDarkBackground()
-}
-
-// EnvNoColor returns true if the environment variables explicitly disable color output
-// by setting NO_COLOR (https://no-color.org/)
-// or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
-// If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE
-// If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset.
-func (o *Output) EnvNoColor() bool {
- return o.environ.Getenv("NO_COLOR") != "" || (o.environ.Getenv("CLICOLOR") == "0" && !o.cliColorForced())
-}
-
-// EnvNoColor returns true if the environment variables explicitly disable color output
-// by setting NO_COLOR (https://no-color.org/)
-// or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
-// If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE
-// If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset.
-func EnvNoColor() bool {
- return output.EnvNoColor()
-}
-
-// EnvColorProfile returns the color profile based on environment variables set
-// Supports NO_COLOR (https://no-color.org/)
-// and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
-// If none of these environment variables are set, this behaves the same as ColorProfile()
-// It will return the Ascii color profile if EnvNoColor() returns true
-// If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0"
-// then the ANSI color profile will be returned.
-func EnvColorProfile() Profile {
- return output.EnvColorProfile()
-}
-
-// EnvColorProfile returns the color profile based on environment variables set
-// Supports NO_COLOR (https://no-color.org/)
-// and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/)
-// If none of these environment variables are set, this behaves the same as ColorProfile()
-// It will return the Ascii color profile if EnvNoColor() returns true
-// If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0"
-// then the ANSI color profile will be returned.
-func (o *Output) EnvColorProfile() Profile {
- if o.EnvNoColor() {
- return Ascii
- }
- p := o.ColorProfile()
- if o.cliColorForced() && p == Ascii {
- return ANSI
- }
- return p
-}
-
-func (o *Output) cliColorForced() bool {
- if forced := o.environ.Getenv("CLICOLOR_FORCE"); forced != "" {
- return forced != "0"
- }
- return false
-}
diff --git a/vendor/github.com/muesli/termenv/termenv_other.go b/vendor/github.com/muesli/termenv/termenv_other.go
deleted file mode 100644
index 93a43b6a..00000000
--- a/vendor/github.com/muesli/termenv/termenv_other.go
+++ /dev/null
@@ -1,30 +0,0 @@
-//go:build js || plan9 || aix
-// +build js plan9 aix
-
-package termenv
-
-import "io"
-
-// ColorProfile returns the supported color profile:
-// ANSI256
-func (o Output) ColorProfile() Profile {
- return ANSI256
-}
-
-func (o Output) foregroundColor() Color {
- // default gray
- return ANSIColor(7)
-}
-
-func (o Output) backgroundColor() Color {
- // default black
- return ANSIColor(0)
-}
-
-// EnableVirtualTerminalProcessing enables virtual terminal processing on
-// Windows for w and returns a function that restores w to its previous state.
-// On non-Windows platforms, or if w does not refer to a terminal, then it
-// returns a non-nil no-op function and no error.
-func EnableVirtualTerminalProcessing(w io.Writer) (func() error, error) {
- return func() error { return nil }, nil
-}
diff --git a/vendor/github.com/muesli/termenv/termenv_posix.go b/vendor/github.com/muesli/termenv/termenv_posix.go
deleted file mode 100644
index c971dd99..00000000
--- a/vendor/github.com/muesli/termenv/termenv_posix.go
+++ /dev/null
@@ -1,17 +0,0 @@
-//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos
-// +build darwin dragonfly freebsd linux netbsd openbsd zos
-
-package termenv
-
-import (
- "golang.org/x/sys/unix"
-)
-
-func isForeground(fd int) bool {
- pgrp, err := unix.IoctlGetInt(fd, unix.TIOCGPGRP)
- if err != nil {
- return false
- }
-
- return pgrp == unix.Getpgrp()
-}
diff --git a/vendor/github.com/muesli/termenv/termenv_solaris.go b/vendor/github.com/muesli/termenv/termenv_solaris.go
deleted file mode 100644
index 27a95a93..00000000
--- a/vendor/github.com/muesli/termenv/termenv_solaris.go
+++ /dev/null
@@ -1,22 +0,0 @@
-//go:build solaris || illumos
-// +build solaris illumos
-
-package termenv
-
-import (
- "golang.org/x/sys/unix"
-)
-
-func isForeground(fd int) bool {
- pgrp, err := unix.IoctlGetInt(fd, unix.TIOCGPGRP)
- if err != nil {
- return false
- }
-
- g, err := unix.Getpgrp()
- if err != nil {
- return false
- }
-
- return pgrp == g
-}
diff --git a/vendor/github.com/muesli/termenv/termenv_unix.go b/vendor/github.com/muesli/termenv/termenv_unix.go
deleted file mode 100644
index bef49ca3..00000000
--- a/vendor/github.com/muesli/termenv/termenv_unix.go
+++ /dev/null
@@ -1,301 +0,0 @@
-//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris zos
-
-package termenv
-
-import (
- "fmt"
- "io"
- "strconv"
- "strings"
- "time"
-
- "golang.org/x/sys/unix"
-)
-
-const (
- // timeout for OSC queries.
- OSCTimeout = 5 * time.Second
-)
-
-// ColorProfile returns the supported color profile:
-// Ascii, ANSI, ANSI256, or TrueColor.
-func (o *Output) ColorProfile() Profile {
- if !o.isTTY() {
- return Ascii
- }
-
- if o.environ.Getenv("GOOGLE_CLOUD_SHELL") == "true" {
- return TrueColor
- }
-
- term := o.environ.Getenv("TERM")
- colorTerm := o.environ.Getenv("COLORTERM")
-
- switch strings.ToLower(colorTerm) {
- case "24bit":
- fallthrough
- case "truecolor":
- if strings.HasPrefix(term, "screen") {
- // tmux supports TrueColor, screen only ANSI256
- if o.environ.Getenv("TERM_PROGRAM") != "tmux" {
- return ANSI256
- }
- }
- return TrueColor
- case "yes":
- fallthrough
- case "true":
- return ANSI256
- }
-
- switch term {
- case
- "alacritty",
- "contour",
- "rio",
- "wezterm",
- "xterm-ghostty",
- "xterm-kitty":
- return TrueColor
- case "linux", "xterm":
- return ANSI
- }
-
- if strings.Contains(term, "256color") {
- return ANSI256
- }
- if strings.Contains(term, "color") {
- return ANSI
- }
- if strings.Contains(term, "ansi") {
- return ANSI
- }
-
- return Ascii
-}
-
-//nolint:mnd
-func (o Output) foregroundColor() Color {
- s, err := o.termStatusReport(10)
- if err == nil {
- c, err := xTermColor(s)
- if err == nil {
- return c
- }
- }
-
- colorFGBG := o.environ.Getenv("COLORFGBG")
- if strings.Contains(colorFGBG, ";") {
- c := strings.Split(colorFGBG, ";")
- i, err := strconv.Atoi(c[0])
- if err == nil {
- return ANSIColor(i)
- }
- }
-
- // default gray
- return ANSIColor(7)
-}
-
-//nolint:mnd
-func (o Output) backgroundColor() Color {
- s, err := o.termStatusReport(11)
- if err == nil {
- c, err := xTermColor(s)
- if err == nil {
- return c
- }
- }
-
- colorFGBG := o.environ.Getenv("COLORFGBG")
- if strings.Contains(colorFGBG, ";") {
- c := strings.Split(colorFGBG, ";")
- i, err := strconv.Atoi(c[len(c)-1])
- if err == nil {
- return ANSIColor(i)
- }
- }
-
- // default black
- return ANSIColor(0)
-}
-
-func (o *Output) waitForData(timeout time.Duration) error {
- fd := o.TTY().Fd()
- tv := unix.NsecToTimeval(int64(timeout))
- var readfds unix.FdSet
- readfds.Set(int(fd)) //nolint:gosec
-
- for {
- n, err := unix.Select(int(fd)+1, &readfds, nil, nil, &tv) //nolint:gosec
- if err == unix.EINTR {
- continue
- }
- if err != nil {
- return err //nolint:wrapcheck
- }
- if n == 0 {
- return fmt.Errorf("timeout")
- }
-
- break
- }
-
- return nil
-}
-
-func (o *Output) readNextByte() (byte, error) {
- if !o.unsafe {
- if err := o.waitForData(OSCTimeout); err != nil {
- return 0, err
- }
- }
-
- var b [1]byte
- n, err := o.TTY().Read(b[:])
- if err != nil {
- return 0, err //nolint:wrapcheck
- }
-
- if n == 0 {
- panic("read returned no data")
- }
-
- return b[0], nil
-}
-
-// readNextResponse reads either an OSC response or a cursor position response:
-// - OSC response: "\x1b]11;rgb:1111/1111/1111\x1b\\"
-// - cursor position response: "\x1b[42;1R"
-func (o *Output) readNextResponse() (response string, isOSC bool, err error) {
- start, err := o.readNextByte()
- if err != nil {
- return "", false, err
- }
-
- // first byte must be ESC
- for start != ESC {
- start, err = o.readNextByte()
- if err != nil {
- return "", false, err
- }
- }
-
- response += string(start)
-
- // next byte is either '[' (cursor position response) or ']' (OSC response)
- tpe, err := o.readNextByte()
- if err != nil {
- return "", false, err
- }
-
- response += string(tpe)
-
- var oscResponse bool
- switch tpe {
- case '[':
- oscResponse = false
- case ']':
- oscResponse = true
- default:
- return "", false, ErrStatusReport
- }
-
- for {
- b, err := o.readNextByte()
- if err != nil {
- return "", false, err
- }
-
- response += string(b)
-
- if oscResponse {
- // OSC can be terminated by BEL (\a) or ST (ESC)
- if b == BEL || strings.HasSuffix(response, string(ESC)) {
- return response, true, nil
- }
- } else {
- // cursor position response is terminated by 'R'
- if b == 'R' {
- return response, false, nil
- }
- }
-
- // both responses have less than 25 bytes, so if we read more, that's an error
- if len(response) > 25 { //nolint:mnd
- break
- }
- }
-
- return "", false, ErrStatusReport
-}
-
-func (o Output) termStatusReport(sequence int) (string, error) {
- // screen/tmux can't support OSC, because they can be connected to multiple
- // terminals concurrently.
- term := o.environ.Getenv("TERM")
- if strings.HasPrefix(term, "screen") || strings.HasPrefix(term, "tmux") || strings.HasPrefix(term, "dumb") {
- return "", ErrStatusReport
- }
-
- tty := o.TTY()
- if tty == nil {
- return "", ErrStatusReport
- }
-
- if !o.unsafe {
- fd := int(tty.Fd()) //nolint:gosec
- // if in background, we can't control the terminal
- if !isForeground(fd) {
- return "", ErrStatusReport
- }
-
- t, err := unix.IoctlGetTermios(fd, tcgetattr)
- if err != nil {
- return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
- }
- defer unix.IoctlSetTermios(fd, tcsetattr, t) //nolint:errcheck
-
- noecho := *t
- noecho.Lflag = noecho.Lflag &^ unix.ECHO
- noecho.Lflag = noecho.Lflag &^ unix.ICANON
- if err := unix.IoctlSetTermios(fd, tcsetattr, &noecho); err != nil {
- return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
- }
- }
-
- // first, send OSC query, which is ignored by terminal which do not support it
- fmt.Fprintf(tty, OSC+"%d;?"+ST, sequence) //nolint:errcheck
-
- // then, query cursor position, should be supported by all terminals
- fmt.Fprintf(tty, CSI+"6n") //nolint:errcheck
-
- // read the next response
- res, isOSC, err := o.readNextResponse()
- if err != nil {
- return "", fmt.Errorf("%s: %s", ErrStatusReport, err)
- }
-
- // if this is not OSC response, then the terminal does not support it
- if !isOSC {
- return "", ErrStatusReport
- }
-
- // read the cursor query response next and discard the result
- _, _, err = o.readNextResponse()
- if err != nil {
- return "", err
- }
-
- // fmt.Println("Rcvd", res[1:])
- return res, nil
-}
-
-// EnableVirtualTerminalProcessing enables virtual terminal processing on
-// Windows for w and returns a function that restores w to its previous state.
-// On non-Windows platforms, or if w does not refer to a terminal, then it
-// returns a non-nil no-op function and no error.
-func EnableVirtualTerminalProcessing(_ io.Writer) (func() error, error) {
- return func() error { return nil }, nil
-}
diff --git a/vendor/github.com/muesli/termenv/termenv_windows.go b/vendor/github.com/muesli/termenv/termenv_windows.go
deleted file mode 100644
index f9b1def0..00000000
--- a/vendor/github.com/muesli/termenv/termenv_windows.go
+++ /dev/null
@@ -1,140 +0,0 @@
-//go:build windows
-// +build windows
-
-package termenv
-
-import (
- "fmt"
- "os"
- "strconv"
-
- "golang.org/x/sys/windows"
-)
-
-func (o *Output) ColorProfile() Profile {
- if !o.isTTY() {
- return Ascii
- }
-
- if o.environ.Getenv("ConEmuANSI") == "ON" {
- return TrueColor
- }
-
- winVersion, _, buildNumber := windows.RtlGetNtVersionNumbers()
- if buildNumber < 10586 || winVersion < 10 {
- // No ANSI support before Windows 10 build 10586.
- if o.environ.Getenv("ANSICON") != "" {
- conVersion := o.environ.Getenv("ANSICON_VER")
- cv, err := strconv.ParseInt(conVersion, 10, 64)
- if err != nil || cv < 181 {
- // No 8 bit color support before v1.81 release.
- return ANSI
- }
-
- return ANSI256
- }
-
- return Ascii
- }
- if buildNumber < 14931 {
- // No true color support before build 14931.
- return ANSI256
- }
-
- return TrueColor
-}
-
-func (o Output) foregroundColor() Color {
- // default gray
- return ANSIColor(7)
-}
-
-func (o Output) backgroundColor() Color {
- // default black
- return ANSIColor(0)
-}
-
-// EnableWindowsANSIConsole enables virtual terminal processing on Windows
-// platforms. This allows the use of ANSI escape sequences in Windows console
-// applications. Ensure this gets called before anything gets rendered with
-// termenv.
-//
-// Returns the original console mode and an error if one occurred.
-func EnableWindowsANSIConsole() (uint32, error) {
- handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
- if err != nil {
- return 0, err
- }
-
- var mode uint32
- err = windows.GetConsoleMode(handle, &mode)
- if err != nil {
- return 0, err
- }
-
- // See https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
- if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
- vtpmode := mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
- if err := windows.SetConsoleMode(handle, vtpmode); err != nil {
- return 0, err
- }
- }
-
- return mode, nil
-}
-
-// RestoreWindowsConsole restores the console mode to a previous state.
-func RestoreWindowsConsole(mode uint32) error {
- handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
- if err != nil {
- return err
- }
-
- return windows.SetConsoleMode(handle, mode)
-}
-
-// EnableVirtualTerminalProcessing enables virtual terminal processing on
-// Windows for o and returns a function that restores o to its previous state.
-// On non-Windows platforms, or if o does not refer to a terminal, then it
-// returns a non-nil no-op function and no error.
-func EnableVirtualTerminalProcessing(o *Output) (restoreFunc func() error, err error) {
- // There is nothing to restore until we set the console mode.
- restoreFunc = func() error {
- return nil
- }
-
- // If o is not a tty, then there is nothing to do.
- tty, ok := o.Writer().(*os.File)
- if tty == nil || !ok {
- return
- }
-
- // Get the current console mode. If there is an error, assume that o is not
- // a terminal, discard the error, and return.
- var mode uint32
- if err2 := windows.GetConsoleMode(windows.Handle(tty.Fd()), &mode); err2 != nil {
- return
- }
-
- // If virtual terminal processing is already set, then there is nothing to
- // do and nothing to restore.
- if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING == windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
- return
- }
-
- // Enable virtual terminal processing. See
- // https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
- if err2 := windows.SetConsoleMode(windows.Handle(tty.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err2 != nil {
- err = fmt.Errorf("windows.SetConsoleMode: %w", err2)
- return
- }
-
- // Set the restore function. We maintain a reference to the tty in the
- // closure (rather than just its handle) to ensure that the tty is not
- // closed by a finalizer.
- restoreFunc = func() error {
- return windows.SetConsoleMode(windows.Handle(tty.Fd()), mode)
- }
-
- return
-}
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/config/config.go b/vendor/github.com/nunnatsa/ginkgolinter/config/config.go
index 1fee023c..e62158ed 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/config/config.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/config/config.go
@@ -63,8 +63,8 @@ func (s *Config) UpdateFromComment(commentGroup []*ast.CommentGroup) {
}
for _, cmnt := range cmntList.List {
- commentLines := strings.Split(cmnt.Text, "\n")
- for _, comment := range commentLines {
+ commentLines := strings.SplitSeq(cmnt.Text, "\n")
+ for comment := range commentLines {
comment = strings.TrimPrefix(comment, "//")
comment = strings.TrimPrefix(comment, "/*")
comment = strings.TrimSuffix(comment, "*/")
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actualarg.go b/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actualarg.go
index 735c03c8..3b49fe57 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actualarg.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actualarg.go
@@ -32,6 +32,7 @@ const (
TBParamArgType
MultiRetsArgType
ErrorMethodArgType
+ ErrorMethodNoErrArgType
ErrorTypeArgType
@@ -51,10 +52,10 @@ func getActualArgPayload(actualExprClone *ast.CallExpr, pass *analysis.Pass, inf
var arg ArgPayload
- if info.HasErrorMethod {
- arg = &ErrorMethodPayload{}
- } else if value.IsExprError(pass, origArgExpr) {
- arg = newErrPayload(origArgExpr, argExprClone, pass)
+ if value.IsExprError(pass, origArgExpr, info.HasErrorMethod) {
+ arg = newErrPayload(origArgExpr, argExprClone, pass, info.HasErrorMethod)
+ } else if info.HasErrorMethod {
+ arg = &ErrorMethodNoErrPayload{}
} else {
switch expr := origArgExpr.(type) {
case *ast.CallExpr:
@@ -179,9 +180,17 @@ type ErrPayload struct {
value.Valuer
}
-func newErrPayload(orig, clone ast.Expr, pass *analysis.Pass) *ErrPayload {
+func newErrPayload(orig, clone ast.Expr, pass *analysis.Pass, withErrorMethod bool) ArgPayload {
+ v := value.GetValuerWithError(orig, clone, pass, withErrorMethod)
+
+ if withErrorMethod {
+ return &ErrorMethodPayload{
+ Valuer: v,
+ }
+ }
+
return &ErrPayload{
- Valuer: value.GetValuer(orig, clone, pass),
+ Valuer: v,
}
}
@@ -189,10 +198,18 @@ func (*ErrPayload) ArgType() ArgType {
return ErrActualArgType | ErrorTypeArgType
}
-type ErrorMethodPayload struct{}
+type ErrorMethodNoErrPayload struct{}
+
+func (ErrorMethodNoErrPayload) ArgType() ArgType {
+ return ErrorMethodNoErrArgType
+}
+
+type ErrorMethodPayload struct {
+ value.Valuer
+}
func (ErrorMethodPayload) ArgType() ArgType {
- return ErrorMethodArgType | ErrorTypeArgType
+ return ErrorMethodArgType | ErrActualArgType | ErrorTypeArgType
}
func parseBinaryExpr(origActualExpr, argExprClone *ast.BinaryExpr, pass *analysis.Pass) ArgPayload {
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/errormatchers.go b/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/errormatchers.go
index 9442ca32..18f2a0b6 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/errormatchers.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/errormatchers.go
@@ -146,7 +146,7 @@ func (m *MatchErrorMatcherWithMatcher) NumArgs() int {
func newMatchErrorMatcher(args []ast.Expr, pass *analysis.Pass) MatchErrorMatcher {
numArgs := len(args)
- if value.IsExprError(pass, args[0]) {
+ if value.IsExprError(pass, args[0], false) {
return &MatchErrorMatcherWithErr{numArgs: numArgs}
}
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/value/value.go b/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/value/value.go
index d615cbe7..1ecd793d 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/value/value.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/value/value.go
@@ -24,6 +24,10 @@ type Valuer interface {
}
func GetValuer(orig, clone ast.Expr, pass *analysis.Pass) Valuer {
+ return GetValuerWithError(orig, clone, pass, false)
+}
+
+func GetValuerWithError(orig, clone ast.Expr, pass *analysis.Pass, withErrorMethod bool) Valuer {
val := New(orig, clone, pass)
unspecified := UnspecifiedValue{
Value: val,
@@ -33,7 +37,7 @@ func GetValuer(orig, clone ast.Expr, pass *analysis.Pass) Valuer {
return unspecified
}
- if IsExprError(pass, orig) {
+ if IsExprError(pass, orig, withErrorMethod) {
return &ErrValue{
Value: val,
err: clone,
@@ -187,7 +191,7 @@ func Is[T any](x any) bool {
return matchType
}
-func IsExprError(pass *analysis.Pass, expr ast.Expr) bool {
+func IsExprError(pass *analysis.Pass, expr ast.Expr, withErrorMethod bool) bool {
actualArgType := pass.TypesInfo.TypeOf(expr)
switch t := actualArgType.(type) {
case *gotypes.Named:
@@ -204,9 +208,14 @@ func IsExprError(pass *analysis.Pass, expr ast.Expr) bool {
case *gotypes.Tuple:
if t.Len() > 0 {
- switch t0 := t.At(0).Type().(type) {
+ retVal := t.At(0).Type()
+ if withErrorMethod {
+ retVal = t.At(t.Len() - 1).Type()
+ }
+
+ switch retVal.(type) {
case *gotypes.Named, *gotypes.Pointer:
- if typecheck.ImplementsError(t0) {
+ if typecheck.ImplementsError(retVal) {
return true
}
}
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/internal/reports/report-builder.go b/vendor/github.com/nunnatsa/ginkgolinter/internal/reports/report-builder.go
index dee88bd2..0302df29 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/internal/reports/report-builder.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/internal/reports/report-builder.go
@@ -97,6 +97,8 @@ func (b *Builder) getMessage() string {
sb.WriteString(strings.Join(b.issues, "; "))
if b.suggestFix && len(b.fixOffer) != 0 {
+ //nolint:staticcheck
+ // staticcheck false positive
sb.WriteString(fmt.Sprintf(". Consider using `%s` instead", b.fixOffer))
}
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/errorequalnilrule.go b/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/errorequalnilrule.go
index b9441ff2..aa03d307 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/errorequalnilrule.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/errorequalnilrule.go
@@ -40,7 +40,7 @@ func (r ErrorEqualNilRule) Apply(gexp *expression.GomegaExpression, config confi
return false
}
- if v, ok := gexp.GetActualArg().(value.Valuer); ok && v.IsFunc() || gexp.ActualArgTypeIs(actual.ErrFuncActualArgType) {
+ if v, ok := gexp.GetActualArg().(value.Valuer); ok && v.IsFunc() && !gexp.ActualArgTypeIs(actual.ErrorMethodArgType) || gexp.ActualArgTypeIs(actual.ErrFuncActualArgType) {
gexp.SetMatcherSucceed()
} else {
gexp.ReverseAssertionFuncLogic()
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/haveoccurredrule.go b/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/haveoccurredrule.go
index f4dea489..f9d68c15 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/haveoccurredrule.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/haveoccurredrule.go
@@ -45,11 +45,13 @@ func (r HaveOccurredRule) Apply(gexp *expression.GomegaExpression, config config
return true
}
- if config.ForceSucceedForFuncs && gexp.GetActualArg().(*actual.ErrPayload).IsFunc() {
- gexp.ReverseAssertionFuncLogic()
- gexp.SetMatcherSucceed()
- reportBuilder.AddIssue(true, "prefer using the Succeed matcher for error function, instead of HaveOccurred")
- return true
+ if config.ForceSucceedForFuncs {
+ if errPayload, ok := gexp.GetActualArg().(*actual.ErrPayload); ok && errPayload.IsFunc() {
+ gexp.ReverseAssertionFuncLogic()
+ gexp.SetMatcherSucceed()
+ reportBuilder.AddIssue(true, "prefer using the Succeed matcher for error function, instead of HaveOccurred")
+ return true
+ }
}
return false
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/succeedrule.go b/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/succeedrule.go
index 93966986..f53beb57 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/succeedrule.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/succeedrule.go
@@ -54,7 +54,7 @@ func (r SucceedRule) Apply(gexp *expression.GomegaExpression, config config.Conf
}
if !gexp.ActualArgTypeIs(actual.ErrorTypeArgType) {
- if gexp.IsActualTuple() {
+ if gexp.IsActualTuple() && !gexp.ActualArgTypeIs(actual.ErrorMethodNoErrArgType) {
reportBuilder.AddIssue(false, "the Success matcher does not support multiple values")
} else {
reportBuilder.AddIssue(false, "asserting a non-error type with Succeed matcher")
@@ -62,13 +62,15 @@ func (r SucceedRule) Apply(gexp *expression.GomegaExpression, config config.Conf
return true
}
- if config.ForceSucceedForFuncs && !gexp.GetActualArg().(*actual.ErrPayload).IsFunc() {
- gexp.ReverseAssertionFuncLogic()
- gexp.SetMatcherHaveOccurred()
+ if config.ForceSucceedForFuncs {
+ if errPayload, ok := gexp.GetActualArg().(*actual.ErrPayload); ok && !errPayload.IsFunc() {
+ gexp.ReverseAssertionFuncLogic()
+ gexp.SetMatcherHaveOccurred()
- reportBuilder.AddIssue(true, "prefer using the HaveOccurred matcher for non-function error value, instead of Succeed")
+ reportBuilder.AddIssue(true, "prefer using the HaveOccurred matcher for non-function error value, instead of Succeed")
- return true
+ return true
+ }
}
return false
diff --git a/vendor/github.com/pelletier/go-toml/v2/.gitignore b/vendor/github.com/pelletier/go-toml/v2/.gitignore
index 4b7c4eda..eaf580df 100644
--- a/vendor/github.com/pelletier/go-toml/v2/.gitignore
+++ b/vendor/github.com/pelletier/go-toml/v2/.gitignore
@@ -5,3 +5,4 @@ cmd/tomljson/tomljson
cmd/tomltestgen/tomltestgen
dist
tests/
+test-results
diff --git a/vendor/github.com/pelletier/go-toml/v2/.golangci.toml b/vendor/github.com/pelletier/go-toml/v2/.golangci.toml
index 067db551..7d2e5b04 100644
--- a/vendor/github.com/pelletier/go-toml/v2/.golangci.toml
+++ b/vendor/github.com/pelletier/go-toml/v2/.golangci.toml
@@ -1,84 +1,76 @@
-[service]
-golangci-lint-version = "1.39.0"
-
-[linters-settings.wsl]
-allow-assign-and-anything = true
-
-[linters-settings.exhaustive]
-default-signifies-exhaustive = true
+version = "2"
[linters]
-disable-all = true
+default = "none"
enable = [
"asciicheck",
"bodyclose",
- "cyclop",
- "deadcode",
- "depguard",
"dogsled",
"dupl",
"durationcheck",
"errcheck",
"errorlint",
"exhaustive",
- # "exhaustivestruct",
- "exportloopref",
"forbidigo",
- # "forcetypeassert",
- "funlen",
- "gci",
- # "gochecknoglobals",
"gochecknoinits",
- "gocognit",
"goconst",
"gocritic",
- "gocyclo",
- "godot",
- "godox",
- # "goerr113",
- "gofmt",
- "gofumpt",
+ "godoclint",
"goheader",
- "goimports",
- "golint",
- "gomnd",
- # "gomoddirectives",
"gomodguard",
"goprintffuncname",
"gosec",
- "gosimple",
"govet",
- # "ifshort",
"importas",
"ineffassign",
"lll",
"makezero",
+ "mirror",
"misspell",
"nakedret",
- "nestif",
"nilerr",
- # "nlreturn",
"noctx",
"nolintlint",
- #"paralleltest",
+ "perfsprint",
"prealloc",
"predeclared",
"revive",
"rowserrcheck",
"sqlclosecheck",
"staticcheck",
- "structcheck",
- "stylecheck",
- # "testpackage",
"thelper",
"tparallel",
- "typecheck",
"unconvert",
"unparam",
"unused",
- "varcheck",
+ "usetesting",
"wastedassign",
"whitespace",
- # "wrapcheck",
- # "wsl"
+]
+
+[linters.settings.exhaustive]
+default-signifies-exhaustive = true
+
+[linters.settings.lll]
+line-length = 150
+
+[[linters.exclusions.rules]]
+path = ".test.go"
+linters = ["goconst", "gosec"]
+
+[[linters.exclusions.rules]]
+path = "main.go"
+linters = ["forbidigo"]
+
+[[linters.exclusions.rules]]
+path = "internal"
+linters = ["revive"]
+text = "(exported|indent-error-flow): "
+
+[formatters]
+enable = [
+ "gci",
+ "gofmt",
+ "gofumpt",
+ "goimports",
]
diff --git a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
index 47f0f591..3208f721 100644
--- a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
+++ b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
@@ -22,7 +22,6 @@ builds:
- linux_riscv64
- windows_amd64
- windows_arm64
- - windows_arm
- darwin_amd64
- darwin_arm64
- id: tomljson
@@ -42,7 +41,6 @@ builds:
- linux_riscv64
- windows_amd64
- windows_arm64
- - windows_arm
- darwin_amd64
- darwin_arm64
- id: jsontoml
@@ -62,7 +60,6 @@ builds:
- linux_arm
- windows_amd64
- windows_arm64
- - windows_arm
- darwin_amd64
- darwin_arm64
universal_binaries:
@@ -77,39 +74,43 @@ universal_binaries:
name_template: jsontoml
archives:
- id: jsontoml
- format: tar.xz
- builds:
+ formats:
+ - tar.xz
+ ids:
- jsontoml
files:
- none*
name_template: "{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}"
- id: tomljson
- format: tar.xz
- builds:
+ formats:
+ - tar.xz
+ ids:
- tomljson
files:
- none*
name_template: "{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}"
- id: tomll
- format: tar.xz
- builds:
+ formats:
+ - tar.xz
+ ids:
- tomll
files:
- none*
name_template: "{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}"
-dockers:
+dockers_v2:
- id: tools
- goos: linux
- goarch: amd64
ids:
- jsontoml
- tomljson
- tomll
- image_templates:
- - "ghcr.io/pelletier/go-toml:latest"
- - "ghcr.io/pelletier/go-toml:{{ .Tag }}"
- - "ghcr.io/pelletier/go-toml:v{{ .Major }}"
- skip_push: false
+ images:
+ - "ghcr.io/pelletier/go-toml"
+ tags:
+ - "latest"
+ - "{{ .Tag }}"
+ - "v{{ .Major }}"
+ platforms:
+ - linux/amd64
checksum:
name_template: 'sha256sums.txt'
snapshot:
diff --git a/vendor/github.com/pelletier/go-toml/v2/AGENTS.md b/vendor/github.com/pelletier/go-toml/v2/AGENTS.md
new file mode 100644
index 00000000..f495afd8
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/AGENTS.md
@@ -0,0 +1,73 @@
+# Agent Guidelines for go-toml
+
+This file provides guidelines for AI agents contributing to go-toml. All agents must follow these rules derived from [CONTRIBUTING.md](./CONTRIBUTING.md).
+
+## Project Overview
+
+go-toml is a TOML library for Go. The goal is to provide an easy-to-use and efficient TOML implementation that gets the job done without getting in the way.
+
+## Code Change Rules
+
+### Backward Compatibility
+
+- **No backward-incompatible changes** unless explicitly discussed and approved
+- Avoid breaking people's programs unless absolutely necessary
+
+### Testing Requirements
+
+- **All bug fixes must include regression tests**
+- **All new code must be tested**
+- Run tests before submitting: `go test -race ./...`
+- Test coverage must not decrease. Check with:
+ ```bash
+ go test -covermode=atomic -coverprofile=coverage.out
+ go tool cover -func=coverage.out
+ ```
+- All lines of code touched by changes should be covered by tests
+
+### Performance Requirements
+
+- go-toml aims to stay efficient; avoid performance regressions
+- Run benchmarks to verify: `go test ./... -bench=. -count=10`
+- Compare results using [benchstat](https://pkg.go.dev/golang.org/x/perf/cmd/benchstat)
+
+### Documentation
+
+- New features or feature extensions must include documentation
+- Documentation lives in [README.md](./README.md) and throughout source code
+
+### Code Style
+
+- Follow existing code format and structure
+- Code must pass `go fmt`
+- Code must pass linting with the same golangci-lint version as CI (see version in `.github/workflows/lint.yml`):
+ ```bash
+ # Install specific version (check lint.yml for current version)
+ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin
+ # Run linter
+ golangci-lint run ./...
+ ```
+
+### Commit Messages
+
+- Commit messages must explain **why** the change is needed
+- Keep messages clear and informative even if details are in the PR description
+
+### Capabilities
+
+go-toml tracks system-level capabilities using [capslock](https://github.com/google/capslock). The baseline is in `capability_baseline.txt` and CI enforces that it does not grow.
+
+- **Do not introduce new capabilities.** PRs that increase the capability set (e.g., adding network access, subprocess execution, syscalls) are unlikely to be accepted.
+- If a change causes the capabilities check to fail, do not update the baseline to make it pass. Instead, rethink the approach to avoid requiring new capabilities.
+- To check locally: `./caps.sh check` (requires `capslock` installed via `go install github.com/google/capslock/cmd/capslock@latest`)
+
+## Pull Request Checklist
+
+Before submitting:
+
+1. Tests pass (`go test -race ./...`)
+2. No backward-incompatible changes (unless discussed)
+3. Relevant documentation added/updated
+4. No performance regression (verify with benchmarks)
+5. Capabilities are not increasing (`./caps.sh check`)
+6. Title is clear and understandable for changelog
diff --git a/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md b/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
index 96ecf9e2..65a3ff49 100644
--- a/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
+++ b/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
@@ -33,7 +33,7 @@ The documentation is present in the [README][readme] and thorough the source
code. On release, it gets updated on [pkg.go.dev][pkg.go.dev]. To make a change
to the documentation, create a pull request with your proposed changes. For
simple changes like that, the easiest way to go is probably the "Fork this
-project and edit the file" button on Github, displayed at the top right of the
+project and edit the file" button on GitHub, displayed at the top right of the
file. Unless it's a trivial change (for example a typo), provide a little bit of
context in your pull request description or commit message.
@@ -92,6 +92,48 @@ However, given GitHub's new policy to _not_ run Actions on pull requests until a
maintainer clicks on button, it is highly recommended that you run them locally
as you make changes.
+### Test across Go versions
+
+The repository includes tooling to test go-toml across multiple Go versions
+(1.11 through 1.25) both locally and in GitHub Actions.
+
+#### Local testing with Docker
+
+Prerequisites: Docker installed and running, Bash shell, `rsync` command.
+
+```bash
+# Test all Go versions in parallel (default)
+./test-go-versions.sh
+
+# Test specific versions
+./test-go-versions.sh 1.21 1.22 1.23
+
+# Test sequentially (slower but uses less resources)
+./test-go-versions.sh --sequential
+
+# Verbose output with custom results directory
+./test-go-versions.sh --verbose --output ./my-results 1.24 1.25
+
+# Show all options
+./test-go-versions.sh --help
+```
+
+The script creates Docker containers for each Go version and runs the full test
+suite. Results are saved to a `test-results/` directory with individual logs and
+a comprehensive summary report.
+
+The script only exits with a non-zero status code if either of the two most
+recent Go versions fail.
+
+#### GitHub Actions testing (maintainers)
+
+1. Go to the **Actions** tab in the GitHub repository
+2. Select **"Go Versions Compatibility Test"** from the workflow list
+3. Click **"Run workflow"**
+4. Optionally customize:
+ - **Go versions**: Space-separated list (e.g., `1.21 1.22 1.23`)
+ - **Execution mode**: Parallel (faster) or sequential (more stable)
+
### Check coverage
We use `go tool cover` to compute test coverage. Most code editors have a way to
@@ -111,7 +153,7 @@ code lowers the coverage.
Go-toml aims to stay efficient. We rely on a set of scenarios executed with Go's
builtin benchmark systems. Because of their noisy nature, containers provided by
-Github Actions cannot be reliably used for benchmarking. As a result, you are
+GitHub Actions cannot be reliably used for benchmarking. As a result, you are
responsible for checking that your changes do not incur a performance penalty.
You can run their following to execute benchmarks:
@@ -138,6 +180,25 @@ description. Pull requests that lower performance will receive more scrutiny.
[benchstat]: https://pkg.go.dev/golang.org/x/perf/cmd/benchstat
+### Capabilities
+
+We use [capslock](https://github.com/google/capslock) to track what
+system-level capabilities (file access, network, syscalls, etc.) each package
+requires. The current baseline is in `capability_baseline.txt`. CI will fail if
+a change introduces a new capability.
+
+**Pull requests that increase the set of capabilities are unlikely to be
+accepted.** go-toml is a parsing library and should not need network access,
+subprocess execution, or other capabilities beyond what it already uses.
+
+If you believe a new capability is genuinely needed, discuss it in an issue
+first. To update the baseline after approval:
+
+```bash
+go install github.com/google/capslock/cmd/capslock@latest
+./caps.sh generate
+```
+
### Style
Try to look around and follow the same format and structure as the rest of the
@@ -168,13 +229,13 @@ Checklist:
1. Decide on the next version number. Use semver. Review commits since last
version to assess.
2. Tag release. For example:
-```
-git checkout v2
-git pull
-git tag v2.2.0
-git push --tags
-```
-3. CI automatically builds a draft Github release. Review it and edit as
+ ```
+ git checkout v2
+ git pull
+ git tag v2.2.0
+ git push --tags
+ ```
+3. CI automatically builds a draft GitHub release. Review it and edit as
necessary. Look for "Other changes". That would indicate a pull request not
labeled properly. Tweak labels and pull request titles until changelog looks
good for users.
diff --git a/vendor/github.com/pelletier/go-toml/v2/Dockerfile b/vendor/github.com/pelletier/go-toml/v2/Dockerfile
index b9e93323..ebd9baba 100644
--- a/vendor/github.com/pelletier/go-toml/v2/Dockerfile
+++ b/vendor/github.com/pelletier/go-toml/v2/Dockerfile
@@ -1,5 +1,6 @@
FROM scratch
ENV PATH "$PATH:/bin"
-COPY tomll /bin/tomll
-COPY tomljson /bin/tomljson
-COPY jsontoml /bin/jsontoml
+ARG TARGETPLATFORM
+COPY $TARGETPLATFORM/tomll /bin/tomll
+COPY $TARGETPLATFORM/tomljson /bin/tomljson
+COPY $TARGETPLATFORM/jsontoml /bin/jsontoml
diff --git a/vendor/github.com/pelletier/go-toml/v2/README.md b/vendor/github.com/pelletier/go-toml/v2/README.md
index 0755e556..067ba3fd 100644
--- a/vendor/github.com/pelletier/go-toml/v2/README.md
+++ b/vendor/github.com/pelletier/go-toml/v2/README.md
@@ -2,7 +2,7 @@
Go library for the [TOML](https://toml.io/en/) format.
-This library supports [TOML v1.0.0](https://toml.io/en/v1.0.0).
+This library supports [TOML v1.1.0](https://toml.io/en/v1.1.0).
[🐞 Bug Reports](https://github.com/pelletier/go-toml/issues)
@@ -21,8 +21,6 @@ documentation.
import "github.com/pelletier/go-toml/v2"
```
-See [Modules](#Modules).
-
## Features
### Stdlib behavior
@@ -30,6 +28,11 @@ See [Modules](#Modules).
As much as possible, this library is designed to behave similarly as the
standard library's `encoding/json`.
+When encoding structs, fields tagged with `omitempty` are omitted if they are
+empty. For `time.Time`, the zero value is considered empty, so timestamps such
+as `created_at` or `updated_at` are not written unless you remove `omitempty`
+from the struct tag or use a pointer type (`*time.Time`).
+
### Performance
While go-toml favors usability, it is written with performance in mind. Most
@@ -67,7 +70,7 @@ this use-case, go-toml provides [`LocalDate`][tld], [`LocalTime`][tlt], and
making them convenient yet unambiguous structures for their respective TOML
representation.
-[ldt]: https://toml.io/en/v1.0.0#local-date-time
+[ldt]: https://toml.io/en/v1.1.0#local-date-time
[tld]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDate
[tlt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalTime
[tldt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDateTime
@@ -107,7 +110,11 @@ type MyConfig struct {
### Unmarshaling
[`Unmarshal`][unmarshal] reads a TOML document and fills a Go structure with its
-content. For example:
+content.
+
+Note that the struct variable names are _capitalized_, while the variables in the toml document are _lowercase_.
+
+For example:
```go
doc := `
@@ -133,6 +140,62 @@ fmt.Println("tags:", cfg.Tags)
[unmarshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Unmarshal
+
+Here is an example using tables with some simple nesting:
+
+```go
+doc := `
+age = 45
+fruits = ["apple", "pear"]
+
+# these are very important!
+[my-variables]
+first = 1
+second = 0.2
+third = "abc"
+
+# this is not so important.
+[my-variables.b]
+bfirst = 123
+`
+
+var Document struct {
+ Age int
+ Fruits []string
+
+ Myvariables struct {
+ First int
+ Second float64
+ Third string
+
+ B struct {
+ Bfirst int
+ }
+ } `toml:"my-variables"`
+}
+
+err := toml.Unmarshal([]byte(doc), &Document)
+if err != nil {
+ panic(err)
+}
+
+fmt.Println("age:", Document.Age)
+fmt.Println("fruits:", Document.Fruits)
+fmt.Println("my-variables.first:", Document.Myvariables.First)
+fmt.Println("my-variables.second:", Document.Myvariables.Second)
+fmt.Println("my-variables.third:", Document.Myvariables.Third)
+fmt.Println("my-variables.B.Bfirst:", Document.Myvariables.B.Bfirst)
+
+// Output:
+// age: 45
+// fruits: [apple pear]
+// my-variables.first: 1
+// my-variables.second: 0.2
+// my-variables.third: abc
+// my-variables.B.Bfirst: 123
+```
+
+
### Marshaling
[`Marshal`][marshal] is the opposite of Unmarshal: it represents a Go structure
@@ -175,17 +238,17 @@ the AST level. See https://pkg.go.dev/github.com/pelletier/go-toml/v2/unstable.
Execution time speedup compared to other Go TOML libraries:
-
-
Benchmark
go-toml v1
BurntSushi/toml
-
-
-
Marshal/HugoFrontMatter-2
1.9x
2.2x
-
Marshal/ReferenceFile/map-2
1.7x
2.1x
-
Marshal/ReferenceFile/struct-2
2.2x
3.0x
-
Unmarshal/HugoFrontMatter-2
2.9x
2.7x
-
Unmarshal/ReferenceFile/map-2
2.6x
2.7x
-
Unmarshal/ReferenceFile/struct-2
4.6x
5.1x
-
+
+
Benchmark
go-toml v1
BurntSushi/toml
+
+
+
Marshal/HugoFrontMatter-2
2.3x
2.4x
+
Marshal/ReferenceFile/map-2
2.2x
2.6x
+
Marshal/ReferenceFile/struct-2
4.9x
5.0x
+
Unmarshal/HugoFrontMatter-2
7.8x
5.9x
+
Unmarshal/ReferenceFile/map-2
6.8x
6.4x
+
Unmarshal/ReferenceFile/struct-2
6.8x
6.3x
+
See more
The table above has the results of the most common use-cases. The table below
@@ -193,40 +256,26 @@ contains the results of all benchmarks, including unrealistic ones. It is
provided for completeness.
-
-
Benchmark
go-toml v1
BurntSushi/toml
-
-
-
Marshal/SimpleDocument/map-2
1.8x
2.7x
-
Marshal/SimpleDocument/struct-2
2.7x
3.8x
-
Unmarshal/SimpleDocument/map-2
3.8x
3.0x
-
Unmarshal/SimpleDocument/struct-2
5.6x
4.1x
-
UnmarshalDataset/example-2
3.0x
3.2x
-
UnmarshalDataset/code-2
2.3x
2.9x
-
UnmarshalDataset/twitter-2
2.6x
2.7x
-
UnmarshalDataset/citm_catalog-2
2.2x
2.3x
-
UnmarshalDataset/canada-2
1.8x
1.5x
-
UnmarshalDataset/config-2
4.1x
2.9x
-
geomean
2.7x
2.8x
-
+
+
Benchmark
go-toml v1
BurntSushi/toml
+
+
+
Marshal/SimpleDocument/map-2
2.1x
3.1x
+
Marshal/SimpleDocument/struct-2
3.4x
4.8x
+
Unmarshal/SimpleDocument/map-2
10.1x
7.0x
+
Unmarshal/SimpleDocument/struct-2
12.4x
8.0x
+
UnmarshalDataset/example-2
8.2x
6.9x
+
UnmarshalDataset/code-2
7.5x
8.3x
+
UnmarshalDataset/twitter-2
9.0x
7.6x
+
UnmarshalDataset/citm_catalog-2
5.0x
4.5x
+
UnmarshalDataset/canada-2
6.4x
4.7x
+
UnmarshalDataset/config-2
10.2x
6.1x
+
geomean
5.8x
5.3x
+
This table can be generated with ./ci.sh benchmark -a -html.
-## Modules
-
-go-toml uses Go's standard modules system.
-
-Installation instructions:
-
-- Go ≥ 1.16: Nothing to do. Use the import in your code. The `go` command deals
- with it automatically.
-- Go ≥ 1.13: `GO111MODULE=on go get github.com/pelletier/go-toml/v2`.
-
-In case of trouble: [Go Modules FAQ][mod-faq].
-
-[mod-faq]: https://github.com/golang/go/wiki/Modules#why-does-installing-a-tool-via-go-get-fail-with-error-cannot-find-main-module
-
## Tools
Go-toml provides three handy command line tools:
@@ -265,304 +314,6 @@ Multiple versions are available on [ghcr.io][docker].
[docker]: https://github.com/pelletier/go-toml/pkgs/container/go-toml
-## Migrating from v1
-
-This section describes the differences between v1 and v2, with some pointers on
-how to get the original behavior when possible.
-
-### Decoding / Unmarshal
-
-#### Automatic field name guessing
-
-When unmarshaling to a struct, if a key in the TOML document does not exactly
-match the name of a struct field or any of the `toml`-tagged field, v1 tries
-multiple variations of the key ([code][v1-keys]).
-
-V2 instead does a case-insensitive matching, like `encoding/json`.
-
-This could impact you if you are relying on casing to differentiate two fields,
-and one of them is a not using the `toml` struct tag. The recommended solution
-is to be specific about tag names for those fields using the `toml` struct tag.
-
-[v1-keys]: https://github.com/pelletier/go-toml/blob/a2e52561804c6cd9392ebf0048ca64fe4af67a43/marshal.go#L775-L781
-
-#### Ignore preexisting value in interface
-
-When decoding into a non-nil `interface{}`, go-toml v1 uses the type of the
-element in the interface to decode the object. For example:
-
-```go
-type inner struct {
- B interface{}
-}
-type doc struct {
- A interface{}
-}
-
-d := doc{
- A: inner{
- B: "Before",
- },
-}
-
-data := `
-[A]
-B = "After"
-`
-
-toml.Unmarshal([]byte(data), &d)
-fmt.Printf("toml v1: %#v\n", d)
-
-// toml v1: main.doc{A:main.inner{B:"After"}}
-```
-
-In this case, field `A` is of type `interface{}`, containing a `inner` struct.
-V1 sees that type and uses it when decoding the object.
-
-When decoding an object into an `interface{}`, V2 instead disregards whatever
-value the `interface{}` may contain and replaces it with a
-`map[string]interface{}`. With the same data structure as above, here is what
-the result looks like:
-
-```go
-toml.Unmarshal([]byte(data), &d)
-fmt.Printf("toml v2: %#v\n", d)
-
-// toml v2: main.doc{A:map[string]interface {}{"B":"After"}}
-```
-
-This is to match `encoding/json`'s behavior. There is no way to make the v2
-decoder behave like v1.
-
-#### Values out of array bounds ignored
-
-When decoding into an array, v1 returns an error when the number of elements
-contained in the doc is superior to the capacity of the array. For example:
-
-```go
-type doc struct {
- A [2]string
-}
-d := doc{}
-err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
-fmt.Println(err)
-
-// (1, 1): unmarshal: TOML array length (3) exceeds destination array length (2)
-```
-
-In the same situation, v2 ignores the last value:
-
-```go
-err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
-fmt.Println("err:", err, "d:", d)
-// err: d: {[one two]}
-```
-
-This is to match `encoding/json`'s behavior. There is no way to make the v2
-decoder behave like v1.
-
-#### Support for `toml.Unmarshaler` has been dropped
-
-This method was not widely used, poorly defined, and added a lot of complexity.
-A similar effect can be achieved by implementing the `encoding.TextUnmarshaler`
-interface and use strings.
-
-#### Support for `default` struct tag has been dropped
-
-This feature adds complexity and a poorly defined API for an effect that can be
-accomplished outside of the library.
-
-It does not seem like other format parsers in Go support that feature (the
-project referenced in the original ticket #202 has not been updated since 2017).
-Given that go-toml v2 should not touch values not in the document, the same
-effect can be achieved by pre-filling the struct with defaults (libraries like
-[go-defaults][go-defaults] can help). Also, string representation is not well
-defined for all types: it creates issues like #278.
-
-The recommended replacement is pre-filling the struct before unmarshaling.
-
-[go-defaults]: https://github.com/mcuadros/go-defaults
-
-#### `toml.Tree` replacement
-
-This structure was the initial attempt at providing a document model for
-go-toml. It allows manipulating the structure of any document, encoding and
-decoding from their TOML representation. While a more robust feature was
-initially planned in go-toml v2, this has been ultimately [removed from
-scope][nodoc] of this library, with no plan to add it back at the moment. The
-closest equivalent at the moment would be to unmarshal into an `interface{}` and
-use type assertions and/or reflection to manipulate the arbitrary
-structure. However this would fall short of providing all of the TOML features
-such as adding comments and be specific about whitespace.
-
-
-#### `toml.Position` are not retrievable anymore
-
-The API for retrieving the position (line, column) of a specific TOML element do
-not exist anymore. This was done to minimize the amount of concepts introduced
-by the library (query path), and avoid the performance hit related to storing
-positions in the absence of a document model, for a feature that seemed to have
-little use. Errors however have gained more detailed position
-information. Position retrieval seems better fitted for a document model, which
-has been [removed from the scope][nodoc] of go-toml v2 at the moment.
-
-### Encoding / Marshal
-
-#### Default struct fields order
-
-V1 emits struct fields order alphabetically by default. V2 struct fields are
-emitted in order they are defined. For example:
-
-```go
-type S struct {
- B string
- A string
-}
-
-data := S{
- B: "B",
- A: "A",
-}
-
-b, _ := tomlv1.Marshal(data)
-fmt.Println("v1:\n" + string(b))
-
-b, _ = tomlv2.Marshal(data)
-fmt.Println("v2:\n" + string(b))
-
-// Output:
-// v1:
-// A = "A"
-// B = "B"
-
-// v2:
-// B = 'B'
-// A = 'A'
-```
-
-There is no way to make v2 encoder behave like v1. A workaround could be to
-manually sort the fields alphabetically in the struct definition, or generate
-struct types using `reflect.StructOf`.
-
-#### No indentation by default
-
-V1 automatically indents content of tables by default. V2 does not. However the
-same behavior can be obtained using [`Encoder.SetIndentTables`][sit]. For example:
-
-```go
-data := map[string]interface{}{
- "table": map[string]string{
- "key": "value",
- },
-}
-
-b, _ := tomlv1.Marshal(data)
-fmt.Println("v1:\n" + string(b))
-
-b, _ = tomlv2.Marshal(data)
-fmt.Println("v2:\n" + string(b))
-
-buf := bytes.Buffer{}
-enc := tomlv2.NewEncoder(&buf)
-enc.SetIndentTables(true)
-enc.Encode(data)
-fmt.Println("v2 Encoder:\n" + string(buf.Bytes()))
-
-// Output:
-// v1:
-//
-// [table]
-// key = "value"
-//
-// v2:
-// [table]
-// key = 'value'
-//
-//
-// v2 Encoder:
-// [table]
-// key = 'value'
-```
-
-[sit]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Encoder.SetIndentTables
-
-#### Keys and strings are single quoted
-
-V1 always uses double quotes (`"`) around strings and keys that cannot be
-represented bare (unquoted). V2 uses single quotes instead by default (`'`),
-unless a character cannot be represented, then falls back to double quotes. As a
-result of this change, `Encoder.QuoteMapKeys` has been removed, as it is not
-useful anymore.
-
-There is no way to make v2 encoder behave like v1.
-
-#### `TextMarshaler` emits as a string, not TOML
-
-Types that implement [`encoding.TextMarshaler`][tm] can emit arbitrary TOML in
-v1. The encoder would append the result to the output directly. In v2 the result
-is wrapped in a string. As a result, this interface cannot be implemented by the
-root object.
-
-There is no way to make v2 encoder behave like v1.
-
-[tm]: https://golang.org/pkg/encoding/#TextMarshaler
-
-#### `Encoder.CompactComments` has been removed
-
-Emitting compact comments is now the default behavior of go-toml. This option
-is not necessary anymore.
-
-#### Struct tags have been merged
-
-V1 used to provide multiple struct tags: `comment`, `commented`, `multiline`,
-`toml`, and `omitempty`. To behave more like the standard library, v2 has merged
-`toml`, `multiline`, `commented`, and `omitempty`. For example:
-
-```go
-type doc struct {
- // v1
- F string `toml:"field" multiline:"true" omitempty:"true" commented:"true"`
- // v2
- F string `toml:"field,multiline,omitempty,commented"`
-}
-```
-
-Has a result, the `Encoder.SetTag*` methods have been removed, as there is just
-one tag now.
-
-#### `Encoder.ArraysWithOneElementPerLine` has been renamed
-
-The new name is `Encoder.SetArraysMultiline`. The behavior should be the same.
-
-#### `Encoder.Indentation` has been renamed
-
-The new name is `Encoder.SetIndentSymbol`. The behavior should be the same.
-
-
-#### Embedded structs behave like stdlib
-
-V1 defaults to merging embedded struct fields into the embedding struct. This
-behavior was unexpected because it does not follow the standard library. To
-avoid breaking backward compatibility, the `Encoder.PromoteAnonymous` method was
-added to make the encoder behave correctly. Given backward compatibility is not
-a problem anymore, v2 does the right thing by default: it follows the behavior
-of `encoding/json`. `Encoder.PromoteAnonymous` has been removed.
-
-[nodoc]: https://github.com/pelletier/go-toml/discussions/506#discussioncomment-1526038
-
-### `query`
-
-go-toml v1 provided the [`go-toml/query`][query] package. It allowed to run
-JSONPath-style queries on TOML files. This feature is not available in v2. For a
-replacement, check out [dasel][dasel].
-
-This package has been removed because it was essentially not supported anymore
-(last commit May 2020), increased the complexity of the code base, and more
-complete solutions exist out there.
-
-[query]: https://github.com/pelletier/go-toml/tree/f99d6bbca119636aeafcf351ee52b3d202782627/query
-[dasel]: https://github.com/TomWright/dasel
-
## Versioning
Expect for parts explicitly marked otherwise, go-toml follows [Semantic
diff --git a/vendor/github.com/pelletier/go-toml/v2/capability_baseline.txt b/vendor/github.com/pelletier/go-toml/v2/capability_baseline.txt
new file mode 100644
index 00000000..c556456c
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/capability_baseline.txt
@@ -0,0 +1 @@
+github.com/pelletier/go-toml/v2: CAPABILITY_REFLECT, CAPABILITY_UNANALYZED, CAPABILITY_UNSAFE_POINTER
diff --git a/vendor/github.com/pelletier/go-toml/v2/caps.sh b/vendor/github.com/pelletier/go-toml/v2/caps.sh
new file mode 100644
index 00000000..31fec2b9
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/caps.sh
@@ -0,0 +1,101 @@
+#!/usr/bin/env bash
+#
+# Generates or checks the capability baseline for go-toml.
+#
+# Usage:
+# ./caps.sh generate # regenerate capability_baseline.txt
+# ./caps.sh check # check that capabilities haven't grown
+#
+# Requires: go, capslock (go install github.com/google/capslock/cmd/capslock@latest)
+
+set -euo pipefail
+
+BASELINE="capability_baseline.txt"
+CAPSLOCK="${CAPSLOCK:-capslock}"
+
+# Capabilities that must never appear in any package.
+FORBIDDEN_CAPS=(
+ CAPABILITY_NETWORK
+ CAPABILITY_CGO
+ CAPABILITY_EXEC
+)
+
+capslock_to_baseline() {
+ "$CAPSLOCK" -packages=. -output=package -granularity=package \
+ | jq -r 'to_entries | sort_by(.key) | .[] | .key + ": " + (.value | sort | join(", "))'
+}
+
+generate() {
+ capslock_to_baseline > "$BASELINE"
+ echo "Wrote $BASELINE"
+}
+
+check() {
+ if [ ! -f "$BASELINE" ]; then
+ echo "ERROR: $BASELINE not found. Run '$0 generate' first."
+ exit 1
+ fi
+
+ current=$(mktemp)
+ trap 'rm -f "$current"' EXIT
+
+ capslock_to_baseline > "$current"
+
+ failed=0
+
+ # Check for forbidden capabilities in current output.
+ for cap in "${FORBIDDEN_CAPS[@]}"; do
+ if grep -q "$cap" "$current"; then
+ echo "FORBIDDEN capability found: $cap"
+ grep "$cap" "$current"
+ failed=1
+ fi
+ done
+
+ # Extract all unique capability names from baseline and current.
+ baseline_caps=$(grep -oE 'CAPABILITY_[A-Z_]+' "$BASELINE" | sort -u)
+ current_caps=$(grep -oE 'CAPABILITY_[A-Z_]+' "$current" | sort -u)
+
+ # Check for new capability names not in the baseline.
+ new_caps=$(comm -13 <(echo "$baseline_caps") <(echo "$current_caps"))
+ if [ -n "$new_caps" ]; then
+ echo "NEW capabilities detected (not in baseline):"
+ echo "$new_caps"
+ failed=1
+ fi
+
+ # Check for new per-package capabilities (a package gained a capability it didn't have before).
+ while IFS=': ' read -r pkg caps; do
+ baseline_pkg_caps=$(grep "^${pkg}:" "$BASELINE" 2>/dev/null | sed 's/^[^:]*: //' || true)
+ if [ -z "$baseline_pkg_caps" ]; then
+ echo "NEW package with capabilities: $pkg: $caps"
+ failed=1
+ continue
+ fi
+ # Check each capability in current for this package
+ for cap in $(echo "$caps" | tr ', ' '\n' | grep -v '^$'); do
+ if ! echo "$baseline_pkg_caps" | grep -q "$cap"; then
+ echo "NEW capability for $pkg: $cap"
+ failed=1
+ fi
+ done
+ done < "$current"
+
+ if [ "$failed" -eq 1 ]; then
+ echo ""
+ echo "FAILED: capabilities have grown."
+ echo "If this is intentional, run '$0 generate' and commit the updated $BASELINE."
+ exit 1
+ fi
+
+ echo "OK: no new capabilities detected."
+}
+
+case "${1:-}" in
+ generate) generate ;;
+ check) check ;;
+ *)
+ echo "Usage: $0 {generate|check}"
+ exit 1
+ ;;
+esac
diff --git a/vendor/github.com/pelletier/go-toml/v2/ci.sh b/vendor/github.com/pelletier/go-toml/v2/ci.sh
index 86217a9b..6b9723bf 100644
--- a/vendor/github.com/pelletier/go-toml/v2/ci.sh
+++ b/vendor/github.com/pelletier/go-toml/v2/ci.sh
@@ -146,13 +146,17 @@ bench() {
pushd "$dir"
+ tags=""
if [ "${replace}" != "" ]; then
- find ./benchmark/ -iname '*.go' -exec sed -i -E "s|github.com/pelletier/go-toml/v2|${replace}|g" {} \;
+ find ./benchmark/ -iname '*.go' -exec sed -i -E "s|github.com/pelletier/go-toml/v2\"|${replace}\"|g" {} \;
go get "${replace}"
+ # The realworld benchmarks use v2-only API and cannot compile against
+ # the other libraries; exclude them from cross-library comparisons.
+ tags="-tags cross_library_benchmark"
fi
export GOMAXPROCS=2
- go test '-bench=^Benchmark(Un)?[mM]arshal' -count=10 -run=Nothing ./... | tee "${out}"
+ go test ${tags} '-bench=^Benchmark(Un)?[mM]arshal' -count=10 -run=Nothing ./... | tee "${out}"
popd
if [ "${branch}" != "HEAD" ]; then
@@ -195,6 +199,11 @@ for line in reversed(lines[2:]):
"%.1fx" % (float(line[3])/v2), # v1
"%.1fx" % (float(line[7])/v2), # bs
])
+
+if not results:
+ print("No benchmark results to display.", file=sys.stderr)
+ sys.exit(1)
+
# move geomean to the end
results.append(results[0])
del results[0]
diff --git a/vendor/github.com/pelletier/go-toml/v2/decode.go b/vendor/github.com/pelletier/go-toml/v2/decode.go
index f0ec3b17..46de2fb4 100644
--- a/vendor/github.com/pelletier/go-toml/v2/decode.go
+++ b/vendor/github.com/pelletier/go-toml/v2/decode.go
@@ -1,6 +1,7 @@
package toml
import (
+ "bytes"
"fmt"
"math"
"strconv"
@@ -22,191 +23,340 @@ func parseInteger(b []byte) (int64, error) {
panic(fmt.Errorf("invalid base '%c', should have been checked by scanIntOrFloat", b[1]))
}
}
-
return parseIntDec(b)
}
-func parseLocalDate(b []byte) (LocalDate, error) {
- // full-date = date-fullyear "-" date-month "-" date-mday
- // date-fullyear = 4DIGIT
- // date-month = 2DIGIT ; 01-12
- // date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year
- var date LocalDate
-
- if len(b) != 10 || b[4] != '-' || b[7] != '-' {
- return date, unstable.NewParserError(b, "dates are expected to have the format YYYY-MM-DD")
+func parseIntHex(b []byte) (int64, error) {
+ var v uint64
+ for _, c := range b[2:] {
+ if c == '_' {
+ continue
+ }
+ var d byte
+ switch {
+ case c >= '0' && c <= '9':
+ d = c - '0'
+ case c >= 'a' && c <= 'f':
+ d = c - 'a' + 10
+ case c >= 'A' && c <= 'F':
+ d = c - 'A' + 10
+ }
+ if v > math.MaxInt64>>4 {
+ return 0, unstable.NewParserError(b, "hexadecimal number is too large to fit in a 64-bit signed integer")
+ }
+ v = v<<4 | uint64(d)
}
+ return int64(v), nil
+}
- var err error
-
- date.Year, err = parseDecimalDigits(b[0:4])
- if err != nil {
- return LocalDate{}, err
+func parseIntOct(b []byte) (int64, error) {
+ var v uint64
+ for _, c := range b[2:] {
+ if c == '_' {
+ continue
+ }
+ if v > math.MaxInt64>>3 {
+ return 0, unstable.NewParserError(b, "octal number is too large to fit in a 64-bit signed integer")
+ }
+ v = v<<3 | uint64(c-'0')
}
+ return int64(v), nil
+}
- date.Month, err = parseDecimalDigits(b[5:7])
- if err != nil {
- return LocalDate{}, err
+func parseIntBin(b []byte) (int64, error) {
+ var v uint64
+ for _, c := range b[2:] {
+ if c == '_' {
+ continue
+ }
+ if v > math.MaxInt64>>1 {
+ return 0, unstable.NewParserError(b, "binary number is too large to fit in a 64-bit signed integer")
+ }
+ v = v<<1 | uint64(c-'0')
}
+ return int64(v), nil
+}
- date.Day, err = parseDecimalDigits(b[8:10])
- if err != nil {
- return LocalDate{}, err
+func parseIntDec(b []byte) (int64, error) {
+ i := 0
+ neg := false
+ switch b[0] {
+ case '-':
+ neg = true
+ i++
+ case '+':
+ i++
}
- if !isValidDate(date.Year, date.Month, date.Day) {
- return LocalDate{}, unstable.NewParserError(b, "impossible date")
+ var limit uint64 = math.MaxInt64
+ if neg {
+ limit = math.MaxInt64 + 1
}
- return date, nil
+ var v uint64
+ for ; i < len(b); i++ {
+ c := b[i]
+ if c == '_' {
+ continue
+ }
+ if v > limit/10 {
+ return 0, unstable.NewParserError(b, "decimal number is too large to fit in a 64-bit signed integer")
+ }
+ v = v*10 + uint64(c-'0')
+ if v > limit {
+ return 0, unstable.NewParserError(b, "decimal number is too large to fit in a 64-bit signed integer")
+ }
+ }
+ if neg {
+ return -int64(v), nil //nolint:gosec // v <= MaxInt64+1, the conversion wraps to the intended negative value
+ }
+ return int64(v), nil //nolint:gosec // v <= MaxInt64
}
-func parseDecimalDigits(b []byte) (int, error) {
- v := 0
-
- for i, c := range b {
- if c < '0' || c > '9' {
- return 0, unstable.NewParserError(b[i:i+1], "expected digit (0-9)")
+func parseFloat(b []byte) (float64, error) {
+ i := 0
+ if len(b) > 0 && (b[0] == '+' || b[0] == '-') {
+ i = 1
+ }
+ if len(b) == i+3 {
+ switch b[i] {
+ case 'i':
+ // inf
+ if b[0] == '-' {
+ return math.Inf(-1), nil
+ }
+ return math.Inf(1), nil
+ case 'n':
+ // nan
+ return math.NaN(), nil
}
- v *= 10
- v += int(c - '0')
}
- return v, nil
-}
-
-func parseDateTime(b []byte) (time.Time, error) {
- // offset-date-time = full-date time-delim full-time
- // full-time = partial-time time-offset
- // time-offset = "Z" / time-numoffset
- // time-numoffset = ( "+" / "-" ) time-hour ":" time-minute
+ // Fast path: a plain decimal whose significand fits in 53 bits and whose
+ // base-10 exponent is within [-22, 22] is parsed exactly with a single
+ // rounding (Clinger's method) straight from the bytes, with no string
+ // allocation and no full strconv parse. This is the common shape for
+ // numeric data (e.g. coordinate lists). Anything outside those bounds, or
+ // with underscores, falls through to strconv, which is the reference.
+ if f, ok := fastParseFloat(b); ok {
+ return f, nil
+ }
+
+ // strconv.ParseFloat is the reference implementation for parsing
+ // floating point numbers. The position of underscores has already been
+ // validated by the parser; strip them so that they do not interfere with
+ // Go's own underscore rules.
+ cleaned := b
+ if bytes.IndexByte(b, '_') >= 0 {
+ cleaned = make([]byte, 0, len(b))
+ for _, c := range b {
+ if c != '_' {
+ cleaned = append(cleaned, c)
+ }
+ }
+ }
- dt, b, err := parseLocalDateTime(b)
+ f, err := strconv.ParseFloat(string(cleaned), 64)
if err != nil {
- return time.Time{}, err
+ return 0, unstable.NewParserError(b, "unable to parse float: %s", err)
}
+ return f, nil
+}
- var zone *time.Location
+// float64pow10 holds the powers of ten that are exactly representable as a
+// float64 (10^0 .. 10^22).
+var float64pow10 = [...]float64{
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
+ 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
+}
- if len(b) == 0 {
- // parser should have checked that when assigning the date time node
- panic("date time should have a timezone")
+// fastParseFloat parses b as a float64 using Clinger's exact method and reports
+// whether it applied. It accepts only plain decimal numbers (optional sign,
+// digits, one optional '.', optional 'e'/'E' exponent) whose significand fits
+// in 53 bits and whose effective base-10 exponent is within [-22, 22]; under
+// those conditions float64(significand) * 10^exp (or / 10^-exp) is the exact,
+// correctly-rounded result, identical to strconv.ParseFloat. It returns
+// ok=false (deferring to strconv) for underscores, hexadecimal floats, large
+// significands or exponents, and any other shape.
+func fastParseFloat(b []byte) (float64, bool) {
+ i := 0
+ neg := false
+ if i < len(b) && (b[i] == '+' || b[i] == '-') {
+ neg = b[i] == '-'
+ i++
}
- if b[0] == 'Z' || b[0] == 'z' {
- b = b[1:]
- zone = time.UTC
- } else {
- const dateTimeByteLen = 6
- if len(b) != dateTimeByteLen {
- return time.Time{}, unstable.NewParserError(b, "invalid date-time timezone")
- }
- var direction int
- switch b[0] {
- case '-':
- direction = -1
- case '+':
- direction = +1
+ var mantissa uint64
+ digits := 0
+ fracDigits := 0
+ sawDot := false
+ sawDigit := false
+ for ; i < len(b); i++ {
+ c := b[i]
+ switch {
+ case c >= '0' && c <= '9':
+ if digits >= 19 {
+ // Too many significant digits to accumulate without risking a
+ // uint64 overflow (and well past the 53-bit exact range).
+ return 0, false
+ }
+ mantissa = mantissa*10 + uint64(c-'0')
+ digits++
+ if sawDot {
+ fracDigits++
+ }
+ sawDigit = true
+ case c == '.':
+ if sawDot {
+ return 0, false
+ }
+ sawDot = true
default:
- return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset character")
- }
-
- if b[3] != ':' {
- return time.Time{}, unstable.NewParserError(b[3:4], "expected a : separator")
+ goto exponent
}
-
- hours, err := parseDecimalDigits(b[1:3])
- if err != nil {
- return time.Time{}, err
- }
- if hours > 23 {
- return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset hours")
- }
-
- minutes, err := parseDecimalDigits(b[4:6])
- if err != nil {
- return time.Time{}, err
+ }
+exponent:
+ if !sawDigit {
+ return 0, false
+ }
+ exp := -fracDigits
+ if i < len(b) && (b[i] == 'e' || b[i] == 'E') {
+ i++
+ esign := 1
+ if i < len(b) && (b[i] == '+' || b[i] == '-') {
+ if b[i] == '-' {
+ esign = -1
+ }
+ i++
}
- if minutes > 59 {
- return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset minutes")
+ if i >= len(b) {
+ return 0, false
}
-
- seconds := direction * (hours*3600 + minutes*60)
- if seconds == 0 {
- zone = time.UTC
- } else {
- zone = time.FixedZone("", seconds)
+ eval := 0
+ for ; i < len(b); i++ {
+ c := b[i]
+ if c < '0' || c > '9' {
+ return 0, false
+ }
+ eval = eval*10 + int(c-'0')
+ if eval > 1000 {
+ return 0, false
+ }
}
- b = b[dateTimeByteLen:]
+ exp += esign * eval
}
-
- if len(b) > 0 {
- return time.Time{}, unstable.NewParserError(b, "extra bytes at the end of the timezone")
+ if i != len(b) {
+ // Trailing bytes (an underscore, a hexadecimal marker, ...).
+ return 0, false
+ }
+ if mantissa > 1<<53 {
+ return 0, false
}
- t := time.Date(
- dt.Year,
- time.Month(dt.Month),
- dt.Day,
- dt.Hour,
- dt.Minute,
- dt.Second,
- dt.Nanosecond,
- zone)
+ f := float64(mantissa)
+ switch {
+ case exp == 0:
+ case exp > 0 && exp <= 22:
+ f *= float64pow10[exp]
+ case exp < 0 && exp >= -22:
+ f /= float64pow10[-exp]
+ default:
+ return 0, false
+ }
+ if neg {
+ f = -f
+ }
+ return f, true
+}
- return t, nil
+func isDecimalDigit(c byte) bool {
+ return c >= '0' && c <= '9'
}
-func parseLocalDateTime(b []byte) (LocalDateTime, []byte, error) {
- var dt LocalDateTime
+// parseLocalDate parses a date of the exact form YYYY-MM-DD and validates
+// its components.
+func parseLocalDate(b []byte) (LocalDate, error) {
+ var date LocalDate
- const localDateTimeByteMinLen = 11
- if len(b) < localDateTimeByteMinLen {
- return dt, nil, unstable.NewParserError(b, "local datetimes are expected to have the format YYYY-MM-DDTHH:MM:SS[.NNNNNNNNN]")
+ if len(b) != 10 || b[4] != '-' || b[7] != '-' {
+ return date, unstable.NewParserError(b, "dates are expected to have the format YYYY-MM-DD")
}
- date, err := parseLocalDate(b[:10])
+ var err error
+ date.Year, err = parseDecimalDigits(b[0:4])
if err != nil {
- return dt, nil, err
+ return date, err
+ }
+ date.Month, err = parseDecimalDigits(b[5:7])
+ if err != nil {
+ return date, err
+ }
+ date.Day, err = parseDecimalDigits(b[8:10])
+ if err != nil {
+ return date, err
}
- dt.LocalDate = date
- sep := b[10]
- if sep != 'T' && sep != ' ' && sep != 't' {
- return dt, nil, unstable.NewParserError(b[10:11], "datetime separator is expected to be T or a space")
+ if date.Month < 1 || date.Month > 12 {
+ return date, unstable.NewParserError(b[5:7], "impossible date")
+ }
+ maxDay := daysIn(date.Month, date.Year)
+ if date.Day < 1 || date.Day > maxDay {
+ return date, unstable.NewParserError(b[8:10], "impossible date")
}
- t, rest, err := parseLocalTime(b[11:])
- if err != nil {
- return dt, nil, err
+ return date, nil
+}
+
+func daysIn(month int, year int) int {
+ switch month {
+ case 2:
+ if isLeapYear(year) {
+ return 29
+ }
+ return 28
+ case 4, 6, 9, 11:
+ return 30
+ default:
+ return 31
}
- dt.LocalTime = t
+}
- return dt, rest, nil
+func isLeapYear(year int) bool {
+ return year%4 == 0 && (year%100 != 0 || year%400 == 0)
+}
+
+// parseDecimalDigits parses a sequence of digits as a decimal number.
+func parseDecimalDigits(b []byte) (int, error) {
+ v := 0
+ for i, c := range b {
+ if !isDecimalDigit(c) {
+ return 0, unstable.NewParserError(b[i:i+1], "expected digit (0-9)")
+ }
+ v = v*10 + int(c-'0')
+ }
+ return v, nil
}
-// parseLocalTime is a bit different because it also returns the remaining
-// []byte that is didn't need. This is to allow parseDateTime to parse those
-// remaining bytes as a timezone.
+// parseLocalTime parses a time of the form HH:MM with optional seconds and an
+// optional fractional part (TOML v1.1.0). It returns the remaining bytes after
+// the time.
func parseLocalTime(b []byte) (LocalTime, []byte, error) {
var (
nspow = [10]int{0, 1e8, 1e7, 1e6, 1e5, 1e4, 1e3, 1e2, 1e1, 1e0}
t LocalTime
)
- // check if b matches to have expected format HH:MM:SS[.NNNNNN]
- const localTimeByteLen = 8
- if len(b) < localTimeByteLen {
- return t, nil, unstable.NewParserError(b, "times are expected to have the format HH:MM:SS[.NNNNNN]")
+ // check if b matches to have expected format HH:MM[:SS[.NNNNNN]]
+ const localTimeByteMinLen = 5
+ if len(b) < localTimeByteMinLen {
+ return t, nil, unstable.NewParserError(b, "times are expected to have the format HH:MM[:SS[.NNNNNN]]")
}
var err error
-
t.Hour, err = parseDecimalDigits(b[0:2])
if err != nil {
return t, nil, err
}
-
if t.Hour > 23 {
return t, nil, unstable.NewParserError(b[0:2], "hour cannot be greater 23")
}
@@ -221,54 +371,53 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
if t.Minute > 59 {
return t, nil, unstable.NewParserError(b[3:5], "minutes cannot be greater 59")
}
- if b[5] != ':' {
- return t, nil, unstable.NewParserError(b[5:6], "expecting colon between minutes and seconds")
- }
- t.Second, err = parseDecimalDigits(b[6:8])
- if err != nil {
- return t, nil, err
- }
+ b = b[5:]
- if t.Second > 60 {
- return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater 60")
- }
+ // Seconds are optional (TOML v1.1.0). Fractional seconds may only appear
+ // when seconds are present:
+ // partial-time = time-hour ":" time-minute [ ":" time-second [ time-secfrac ] ]
+ secondsPresent := false
+
+ if len(b) >= 1 && b[0] == ':' {
+ if len(b) < 3 {
+ return t, nil, unstable.NewParserError(b, "incomplete seconds")
+ }
+
+ t.Second, err = parseDecimalDigits(b[1:3])
+ if err != nil {
+ return t, nil, err
+ }
+
+ if t.Second > 59 {
+ return t, nil, unstable.NewParserError(b[1:3], "seconds cannot be greater than 59")
+ }
- b = b[8:]
+ b = b[3:]
+ secondsPresent = true
+ }
- if len(b) >= 1 && b[0] == '.' {
+ if secondsPresent && len(b) >= 1 && b[0] == '.' {
frac := 0
precision := 0
digits := 0
for i, c := range b[1:] {
- if !isDigit(c) {
+ if !isDecimalDigit(c) {
if i == 0 {
return t, nil, unstable.NewParserError(b[0:1], "need at least one digit after fraction point")
}
break
}
digits++
-
- const maxFracPrecision = 9
- if i >= maxFracPrecision {
- // go-toml allows decoding fractional seconds
- // beyond the supported precision of 9
- // digits. It truncates the fractional component
- // to the supported precision and ignores the
- // remaining digits.
- //
- // https://github.com/pelletier/go-toml/discussions/707
- continue
+ if i < 9 {
+ frac = frac*10 + int(c-'0')
+ precision++
}
-
- frac *= 10
- frac += int(c - '0')
- precision++
}
- if precision == 0 {
- return t, nil, unstable.NewParserError(b[:1], "nanoseconds need at least one digit")
+ if digits == 0 {
+ return t, nil, unstable.NewParserError(b[0:1], "need at least one digit after fraction point")
}
t.Nanosecond = frac * nspow[precision]
@@ -279,272 +428,111 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
return t, b, nil
}
-//nolint:cyclop
-func parseFloat(b []byte) (float64, error) {
- if len(b) == 4 && (b[0] == '+' || b[0] == '-') && b[1] == 'n' && b[2] == 'a' && b[3] == 'n' {
- return math.NaN(), nil
- }
-
- cleaned, err := checkAndRemoveUnderscoresFloats(b)
- if err != nil {
- return 0, err
- }
-
- if cleaned[0] == '.' {
- return 0, unstable.NewParserError(b, "float cannot start with a dot")
- }
-
- if cleaned[len(cleaned)-1] == '.' {
- return 0, unstable.NewParserError(b, "float cannot end with a dot")
- }
-
- dotAlreadySeen := false
- for i, c := range cleaned {
- if c == '.' {
- if dotAlreadySeen {
- return 0, unstable.NewParserError(b[i:i+1], "float can have at most one decimal point")
- }
- if !isDigit(cleaned[i-1]) {
- return 0, unstable.NewParserError(b[i-1:i+1], "float decimal point must be preceded by a digit")
- }
- if !isDigit(cleaned[i+1]) {
- return 0, unstable.NewParserError(b[i:i+2], "float decimal point must be followed by a digit")
- }
- dotAlreadySeen = true
- }
- }
-
- start := 0
- if cleaned[0] == '+' || cleaned[0] == '-' {
- start = 1
- }
- if cleaned[start] == '0' && len(cleaned) > start+1 && isDigit(cleaned[start+1]) {
- return 0, unstable.NewParserError(b, "float integer part cannot have leading zeroes")
- }
-
- f, err := strconv.ParseFloat(string(cleaned), 64)
- if err != nil {
- return 0, unstable.NewParserError(b, "unable to parse float: %w", err)
- }
-
- return f, nil
-}
-
-func parseIntHex(b []byte) (int64, error) {
- cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:])
- if err != nil {
- return 0, err
- }
-
- i, err := strconv.ParseInt(string(cleaned), 16, 64)
- if err != nil {
- return 0, unstable.NewParserError(b, "couldn't parse hexadecimal number: %w", err)
- }
-
- return i, nil
-}
+// parseLocalDateTime parses a local date time of the form
+// YYYY-MM-DD(T| )HH:MM:SS[.NNNNNN]. It returns the remaining bytes after the
+// date-time.
+func parseLocalDateTime(b []byte) (LocalDateTime, []byte, error) {
+ var dt LocalDateTime
-func parseIntOct(b []byte) (int64, error) {
- cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:])
- if err != nil {
- return 0, err
+ const localDateTimeByteMinLen = 11
+ if len(b) < localDateTimeByteMinLen {
+ return dt, nil, unstable.NewParserError(b, "local datetimes are expected to have the format YYYY-MM-DDTHH:MM[:SS[.NNNNNNNNN]]")
}
- i, err := strconv.ParseInt(string(cleaned), 8, 64)
+ date, err := parseLocalDate(b[:10])
if err != nil {
- return 0, unstable.NewParserError(b, "couldn't parse octal number: %w", err)
+ return dt, nil, err
}
+ dt.LocalDate = date
- return i, nil
-}
-
-func parseIntBin(b []byte) (int64, error) {
- cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:])
- if err != nil {
- return 0, err
+ sep := b[10]
+ if sep != 'T' && sep != ' ' && sep != 't' {
+ return dt, nil, unstable.NewParserError(b[10:11], "datetime separator is expected to be T or a space")
}
- i, err := strconv.ParseInt(string(cleaned), 2, 64)
+ t, rest, err := parseLocalTime(b[11:])
if err != nil {
- return 0, unstable.NewParserError(b, "couldn't parse binary number: %w", err)
+ return dt, nil, err
}
+ dt.LocalTime = t
- return i, nil
-}
-
-func isSign(b byte) bool {
- return b == '+' || b == '-'
+ return dt, rest, nil
}
-func parseIntDec(b []byte) (int64, error) {
- cleaned, err := checkAndRemoveUnderscoresIntegers(b)
- if err != nil {
- return 0, err
- }
-
- startIdx := 0
-
- if isSign(cleaned[0]) {
- startIdx++
- }
-
- if len(cleaned) > startIdx+1 && cleaned[startIdx] == '0' {
- return 0, unstable.NewParserError(b, "leading zero not allowed on decimal number")
- }
-
- i, err := strconv.ParseInt(string(cleaned), 10, 64)
+// parseDateTime parses a date-time with a timezone offset (Z or +/-HH:MM).
+func parseDateTime(b []byte) (time.Time, error) {
+ dt, b, err := parseLocalDateTime(b)
if err != nil {
- return 0, unstable.NewParserError(b, "couldn't parse decimal number: %w", err)
- }
-
- return i, nil
-}
-
-func checkAndRemoveUnderscoresIntegers(b []byte) ([]byte, error) {
- start := 0
- if b[start] == '+' || b[start] == '-' {
- start++
- }
-
- if len(b) == start {
- return b, nil
+ return time.Time{}, err
}
- if b[start] == '_' {
- return nil, unstable.NewParserError(b[start:start+1], "number cannot start with underscore")
- }
+ var zone *time.Location
- if b[len(b)-1] == '_' {
- return nil, unstable.NewParserError(b[len(b)-1:], "number cannot end with underscore")
+ if len(b) == 0 {
+ // parser should have checked that there is a timezone
+ return time.Time{}, unstable.NewParserError(b, "date-time is missing timezone")
}
- // fast path
- i := 0
- for ; i < len(b); i++ {
- if b[i] == '_' {
- break
+ if b[0] == 'Z' || b[0] == 'z' {
+ b = b[1:]
+ zone = time.UTC
+ } else {
+ const dateTimeByteLen = 6
+ if len(b) != dateTimeByteLen {
+ return time.Time{}, unstable.NewParserError(b, "invalid date-time timezone")
}
- }
- if i == len(b) {
- return b, nil
- }
-
- before := false
- cleaned := make([]byte, i, len(b))
- copy(cleaned, b)
-
- for i++; i < len(b); i++ {
- c := b[i]
- if c == '_' {
- if !before {
- return nil, unstable.NewParserError(b[i-1:i+1], "number must have at least one digit between underscores")
- }
- before = false
- } else {
- before = true
- cleaned = append(cleaned, c)
+ var direction int
+ switch b[0] {
+ case '-':
+ direction = -1
+ case '+':
+ direction = +1
+ default:
+ return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset character")
}
- }
-
- return cleaned, nil
-}
-
-func checkAndRemoveUnderscoresFloats(b []byte) ([]byte, error) {
- if b[0] == '_' {
- return nil, unstable.NewParserError(b[0:1], "number cannot start with underscore")
- }
- if b[len(b)-1] == '_' {
- return nil, unstable.NewParserError(b[len(b)-1:], "number cannot end with underscore")
- }
-
- // fast path
- i := 0
- for ; i < len(b); i++ {
- if b[i] == '_' {
- break
+ if b[3] != ':' {
+ return time.Time{}, unstable.NewParserError(b[3:4], "expected a : separator")
}
- }
- if i == len(b) {
- return b, nil
- }
- before := false
- cleaned := make([]byte, 0, len(b))
+ hours, err := parseDecimalDigits(b[1:3])
+ if err != nil {
+ return time.Time{}, err
+ }
+ if hours > 23 {
+ return time.Time{}, unstable.NewParserError(b[1:3], "invalid timezone offset hours")
+ }
- for i := 0; i < len(b); i++ {
- c := b[i]
+ minutes, err := parseDecimalDigits(b[4:6])
+ if err != nil {
+ return time.Time{}, err
+ }
+ if minutes > 59 {
+ return time.Time{}, unstable.NewParserError(b[4:6], "invalid timezone offset minutes")
+ }
- switch c {
- case '_':
- if !before {
- return nil, unstable.NewParserError(b[i-1:i+1], "number must have at least one digit between underscores")
- }
- if i < len(b)-1 && (b[i+1] == 'e' || b[i+1] == 'E') {
- return nil, unstable.NewParserError(b[i+1:i+2], "cannot have underscore before exponent")
- }
- before = false
- case '+', '-':
- // signed exponents
- cleaned = append(cleaned, c)
- before = false
- case 'e', 'E':
- if i < len(b)-1 && b[i+1] == '_' {
- return nil, unstable.NewParserError(b[i+1:i+2], "cannot have underscore after exponent")
- }
- cleaned = append(cleaned, c)
- case '.':
- if i < len(b)-1 && b[i+1] == '_' {
- return nil, unstable.NewParserError(b[i+1:i+2], "cannot have underscore after decimal point")
- }
- if i > 0 && b[i-1] == '_' {
- return nil, unstable.NewParserError(b[i-1:i], "cannot have underscore before decimal point")
- }
- cleaned = append(cleaned, c)
- default:
- before = true
- cleaned = append(cleaned, c)
+ seconds := direction * (hours*3600 + minutes*60)
+ if seconds == 0 {
+ zone = time.UTC
+ } else {
+ zone = time.FixedZone("", seconds)
}
+ b = b[dateTimeByteLen:]
}
- return cleaned, nil
-}
-
-// isValidDate checks if a provided date is a date that exists.
-func isValidDate(year int, month int, day int) bool {
- return month > 0 && month < 13 && day > 0 && day <= daysIn(month, year)
-}
-
-// daysBefore[m] counts the number of days in a non-leap year
-// before month m begins. There is an entry for m=12, counting
-// the number of days before January of next year (365).
-var daysBefore = [...]int32{
- 0,
- 31,
- 31 + 28,
- 31 + 28 + 31,
- 31 + 28 + 31 + 30,
- 31 + 28 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
-}
-
-func daysIn(m int, year int) int {
- if m == 2 && isLeap(year) {
- return 29
+ if len(b) > 0 {
+ return time.Time{}, unstable.NewParserError(b, "extra bytes at the end of the timezone")
}
- return int(daysBefore[m] - daysBefore[m-1])
-}
-func isLeap(year int) bool {
- return year%4 == 0 && (year%100 != 0 || year%400 == 0)
-}
+ t := time.Date(
+ dt.Year,
+ time.Month(dt.Month),
+ dt.Day,
+ dt.Hour,
+ dt.Minute,
+ dt.Second,
+ dt.Nanosecond,
+ zone)
-func isDigit(r byte) bool {
- return r >= '0' && r <= '9'
+ return t, nil
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/decode_fused.go b/vendor/github.com/pelletier/go-toml/v2/decode_fused.go
new file mode 100644
index 00000000..9de2d652
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/decode_fused.go
@@ -0,0 +1,362 @@
+package toml
+
+import (
+ "errors"
+ "reflect"
+ "strings"
+
+ "github.com/pelletier/go-toml/v2/internal/parserbridge"
+ "github.com/pelletier/go-toml/v2/unstable"
+)
+
+// unmarshalFused decodes a whole document into a native map[string]interface{}
+// tree with no reflection on the document structure, and without building an
+// AST for table headers and scalar key-values. Only container values (arrays
+// and inline tables) are parsed into the parser arena, so that the seen-tracker
+// can validate them and decodeAny can presize the resulting slices and maps —
+// the AST is what makes that cheap O(1) presizing possible.
+//
+// It is used when the target is a fully generic value (interface{} or
+// map[string]interface{}) and the unmarshaler interface is disabled. The
+// seen-tracker validates the document (duplicate keys, type consistency), so
+// the builder creates and merges containers without revalidating. Strict mode
+// never applies to a generic target (a map has no "unknown fields"), and
+// captures never apply (a generic value implements no Unmarshaler).
+func (d *decoder) unmarshalFused(root reflect.Value, data []byte) error {
+ var m map[string]interface{}
+ if !root.IsNil() {
+ // Decode into (merge with) an existing generic map when present.
+ if em, ok := root.Interface().(map[string]interface{}); ok {
+ m = em
+ }
+ }
+ if m == nil {
+ m = map[string]interface{}{}
+ }
+
+ if err := d.fusedDocument(m, data); err != nil {
+ return d.wrapFusedError(data, err)
+ }
+
+ if root.CanSet() {
+ root.Set(reflect.ValueOf(m))
+ }
+ return nil
+}
+
+// fusedDocument runs the top-level expression loop, mirroring
+// Parser.NextExpression but storing values directly into native maps.
+func (d *decoder) fusedDocument(m map[string]interface{}, b []byte) error {
+ cur := m
+ for {
+ b = fusedSkipWS(b)
+ if len(b) == 0 {
+ return nil
+ }
+ switch b[0] {
+ case '\n':
+ b = b[1:]
+ case '\r':
+ if len(b) > 1 && b[1] == '\n' {
+ b = b[2:]
+ continue
+ }
+ return unstable.NewParserError(b[:1], "expected newline but got %#U", b[0])
+ case '#':
+ _, rest, err := parserbridge.ScanComment(b)
+ if err != nil {
+ return err
+ }
+ rest, err = fusedConsumeEOL(rest)
+ if err != nil {
+ return err
+ }
+ b = rest
+ case '[':
+ rest, err := d.fusedTable(b, m, &cur)
+ if err != nil {
+ return err
+ }
+ b = rest
+ default:
+ rest, err := d.fusedKeyVal(b, cur)
+ if err != nil {
+ return err
+ }
+ b = rest
+ }
+ }
+}
+
+// fusedTable handles a [table] or [[array table]] header. b starts at '['. It
+// updates *cur to the table the following key-values belong to.
+func (d *decoder) fusedTable(b []byte, root map[string]interface{}, cur *map[string]interface{}) ([]byte, error) {
+ arrayTable := len(b) > 1 && b[1] == '['
+
+ var start []byte
+ if arrayTable {
+ start = fusedSkipWS(b[2:])
+ } else {
+ start = fusedSkipWS(b[1:])
+ }
+
+ var err error
+ var rawKey []byte
+ d.keyParts, rawKey, b, err = parserbridge.ScanKey(&d.p, start, d.keyParts[:0])
+ if err != nil {
+ return nil, err
+ }
+
+ if arrayTable {
+ if len(b) < 2 || b[0] != ']' || b[1] != ']' {
+ return nil, unstable.NewParserError(fusedHL1(b), "expected ']]' to close array table name")
+ }
+ b = b[2:]
+ } else {
+ if len(b) == 0 || b[0] != ']' {
+ return nil, unstable.NewParserError(fusedHL1(b), "expected ']' to close table name")
+ }
+ b = b[1:]
+ }
+
+ // The whole expression (including its line termination) is parsed before
+ // it is validated, to keep error precedence identical to the AST path.
+ b, err = d.fusedFinishLine(b)
+ if err != nil {
+ return nil, err
+ }
+
+ if arrayTable {
+ first, err := d.seen.CheckArrayTable(d.keyParts)
+ if err != nil {
+ return nil, d.fusedSeenError(rawKey, d.keyParts, err)
+ }
+ *cur = d.anyArrayTableParts(root, d.keyParts, first)
+ } else {
+ if _, err := d.seen.CheckTable(d.keyParts); err != nil {
+ return nil, d.fusedSeenError(rawKey, d.keyParts, err)
+ }
+ *cur = d.anyTableParts(root, d.keyParts)
+ }
+ return b, nil
+}
+
+// fusedKeyVal handles a `key = value` expression relative to the current table
+// cur. b starts at the first character of the key.
+func (d *decoder) fusedKeyVal(b []byte, cur map[string]interface{}) ([]byte, error) {
+ var err error
+ var rawKey []byte
+ d.keyParts, rawKey, b, err = parserbridge.ScanKey(&d.p, b, d.keyParts[:0])
+ if err != nil {
+ return nil, err
+ }
+ if len(b) == 0 || b[0] != '=' {
+ return nil, unstable.NewParserError(fusedHL1(b), "expected '=' after key")
+ }
+ b = fusedSkipWS(b[1:])
+ if len(b) == 0 {
+ return nil, unstable.NewParserError(b, "expected value, not end of input")
+ }
+
+ if c := b[0]; c == '[' || c == '{' {
+ // Container value: build its AST so the seen-tracker can validate it
+ // and decodeAny can presize the resulting slices and maps.
+ nodeAny, rest, err := parserbridge.ParseValue(&d.p, b)
+ if err != nil {
+ return nil, err
+ }
+ node := nodeAny.(*unstable.Node)
+ rest, err = d.fusedFinishLine(rest)
+ if err != nil {
+ return nil, err
+ }
+ leafID, err := d.seen.CheckKeyValue(d.keyParts)
+ if err != nil {
+ return nil, d.fusedSeenError(rawKey, d.keyParts, err)
+ }
+ if err := d.seen.CheckValueUnder(leafID, node); err != nil {
+ return nil, d.fusedSeenError(rawKey, d.keyParts, err)
+ }
+ av, err := d.decodeAny(node)
+ if err != nil {
+ return nil, err
+ }
+ d.setFusedLeaf(cur, d.keyParts, av)
+ return rest, nil
+ }
+
+ // Scalar value: scan it without building a node, then validate and convert
+ // it natively.
+ k, _, value, rest, err := parserbridge.ScanScalar(&d.p, b)
+ if err != nil {
+ return nil, err
+ }
+ kind := unstable.Kind(k)
+ rest, err = d.fusedFinishLine(rest)
+ if err != nil {
+ return nil, err
+ }
+ if _, err := d.seen.CheckKeyValue(d.keyParts); err != nil {
+ return nil, d.fusedSeenError(rawKey, d.keyParts, err)
+ }
+ av, err := d.fusedScalar(kind, value)
+ if err != nil {
+ return nil, err
+ }
+ d.setFusedLeaf(cur, d.keyParts, av)
+ return rest, nil
+}
+
+// fusedSeenError turns a bare error returned by a SeenTracker parts-method
+// into a ParserError carrying the position (the raw key span) and key path of
+// the offending expression, so that it is reported as a DecodeError with
+// context. It mirrors decoder.wrapSeenError for the fused (AST-less) path.
+func (d *decoder) fusedSeenError(rawKey []byte, parts [][]byte, err error) error {
+ key := make(Key, len(parts))
+ for i, p := range parts {
+ key[i] = string(p)
+ }
+ return &unstable.ParserError{
+ Highlight: rawKey,
+ Message: strings.TrimPrefix(err.Error(), "toml: "),
+ Key: key,
+ }
+}
+
+// fusedScalar converts a scanned scalar value into the native Go value used
+// for generic targets. It mirrors the scalar cases of decodeAny.
+func (d *decoder) fusedScalar(kind unstable.Kind, value []byte) (interface{}, error) {
+ switch kind {
+ case unstable.String:
+ return string(value), nil
+ case unstable.Integer:
+ i, err := parseInteger(value)
+ return i, err
+ case unstable.Float:
+ f, err := parseFloat(value)
+ return f, err
+ case unstable.Bool:
+ return value[0] == 't', nil
+ case unstable.DateTime:
+ t, err := parseDateTime(value)
+ return t, err
+ case unstable.LocalDateTime:
+ dt, rest, err := parseLocalDateTime(value)
+ if err != nil {
+ return nil, err
+ }
+ if len(rest) > 0 {
+ return nil, unstable.NewParserError(rest, "extra characters at the end of a local date time")
+ }
+ return dt, nil
+ case unstable.LocalDate:
+ date, err := parseLocalDate(value)
+ return date, err
+ case unstable.LocalTime:
+ t, rest, err := parseLocalTime(value)
+ if err != nil {
+ return nil, err
+ }
+ if len(rest) > 0 {
+ return nil, unstable.NewParserError(rest, "extra characters at the end of a local time")
+ }
+ return t, nil
+ default:
+ return nil, unstable.NewParserError(value, "unsupported value kind %s", kind)
+ }
+}
+
+// anyTableParts navigates a [table] header (given its key parts) to the map it
+// designates, creating intermediate tables as needed.
+func (d *decoder) anyTableParts(m map[string]interface{}, parts [][]byte) map[string]interface{} {
+ cur := m
+ for _, p := range parts {
+ cur = d.anyChildTable(cur, d.intern(p))
+ }
+ return cur
+}
+
+// anyArrayTableParts navigates a [[array table]] header (given its key parts),
+// appends a fresh element to the designated array, and returns it. first is
+// true the first time this header is seen, in which case any pre-existing array
+// (from a reused target) is reset.
+func (d *decoder) anyArrayTableParts(m map[string]interface{}, parts [][]byte, first bool) map[string]interface{} {
+ cur := m
+ name := d.intern(parts[0])
+ for i := 1; i < len(parts); i++ {
+ cur = d.anyChildTable(cur, name)
+ name = d.intern(parts[i])
+ }
+ s, _ := cur[name].([]interface{})
+ if first {
+ s = s[:0]
+ }
+ elem := map[string]interface{}{}
+ cur[name] = append(s, elem)
+ return elem
+}
+
+// setFusedLeaf assigns av at the (possibly dotted) key parts within cur,
+// creating intermediate maps as needed.
+func (d *decoder) setFusedLeaf(cur map[string]interface{}, parts [][]byte, av interface{}) {
+ for i := 0; i < len(parts)-1; i++ {
+ cur = d.anyChildTable(cur, d.intern(parts[i]))
+ }
+ cur[d.intern(parts[len(parts)-1])] = av
+}
+
+// wrapFusedError gives document context to errors produced by the fused
+// decoder.
+func (d *decoder) wrapFusedError(data []byte, err error) error {
+ var perr *unstable.ParserError
+ if errors.As(err, &perr) && len(perr.Highlight) == 0 {
+ // Mirror NextExpression: give end-of-input errors a usable position by
+ // extending the empty highlight to the last byte of the document.
+ if offset := cap(data) - cap(perr.Highlight); offset > 0 && offset == len(data) {
+ perr.Highlight = data[offset-1 : offset]
+ }
+ }
+ return d.wrapError(data, err)
+}
+
+func fusedSkipWS(b []byte) []byte {
+ for len(b) > 0 && (b[0] == ' ' || b[0] == '\t') {
+ b = b[1:]
+ }
+ return b
+}
+
+func fusedConsumeEOL(b []byte) ([]byte, error) {
+ if len(b) == 0 {
+ return b, nil
+ }
+ switch b[0] {
+ case '\n':
+ return b[1:], nil
+ case '\r':
+ if len(b) > 1 && b[1] == '\n' {
+ return b[2:], nil
+ }
+ }
+ return nil, unstable.NewParserError(b[:1], "expected newline but got %#U", b[0])
+}
+
+// fusedFinishLine consumes `ws [comment] (newline|eof)` after an expression.
+func (d *decoder) fusedFinishLine(b []byte) ([]byte, error) {
+ b = fusedSkipWS(b)
+ if len(b) > 0 && b[0] == '#' {
+ _, rest, err := parserbridge.ScanComment(b)
+ if err != nil {
+ return nil, err
+ }
+ b = rest
+ }
+ return fusedConsumeEOL(b)
+}
+
+func fusedHL1(b []byte) []byte {
+ if len(b) > 0 {
+ return b[:1]
+ }
+ return b
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/errors.go b/vendor/github.com/pelletier/go-toml/v2/errors.go
index 309733f1..8e10b128 100644
--- a/vendor/github.com/pelletier/go-toml/v2/errors.go
+++ b/vendor/github.com/pelletier/go-toml/v2/errors.go
@@ -1,11 +1,10 @@
package toml
import (
- "fmt"
+ "errors"
"strconv"
"strings"
- "github.com/pelletier/go-toml/v2/internal/danger"
"github.com/pelletier/go-toml/v2/unstable"
)
@@ -47,13 +46,24 @@ func (s *StrictMissingError) String() string {
if i > 0 {
buf.WriteString("\n---\n")
}
-
buf.WriteString(e.String())
}
return buf.String()
}
+// Unwrap returns wrapped decode errors
+//
+// Implements errors.Join() interface.
+func (s *StrictMissingError) Unwrap() []error {
+ errs := make([]error, len(s.Errors))
+ for i := range s.Errors {
+ errs[i] = &s.Errors[i]
+ }
+ return errs
+}
+
+// Key represents a TOML key as a sequence of key parts.
type Key []string
// Error returns the error message contained in the DecodeError.
@@ -61,7 +71,8 @@ func (e *DecodeError) Error() string {
return "toml: " + e.message
}
-// String returns the human-readable contextualized error. This string is multi-line.
+// String returns the human-readable contextualized error. This string is
+// multi-line.
func (e *DecodeError) String() string {
return e.human
}
@@ -72,181 +83,151 @@ func (e *DecodeError) Position() (row int, column int) {
return e.line, e.column
}
-// Key that was being processed when the error occurred. The key is present only
-// if this DecodeError is part of a StrictMissingError.
+// Key that was being processed when the error occurred.
func (e *DecodeError) Key() Key {
return e.key
}
-// decodeErrorFromHighlight creates a DecodeError referencing a highlighted
-// range of bytes from document.
-//
-// highlight needs to be a sub-slice of document, or this function panics.
-//
-// The function copies all bytes used in DecodeError, so that document and
-// highlight can be freely deallocated.
-//
-//nolint:funlen
+// wrapDecodeError creates a DecodeError from a ParserError. The highlight of
+// the ParserError needs to be a subslice of the document.
func wrapDecodeError(document []byte, de *unstable.ParserError) *DecodeError {
- offset := danger.SubsliceOffset(document, de.Highlight)
-
- errMessage := de.Error()
- errLine, errColumn := positionAtEnd(document[:offset])
- before, after := linesOfContext(document, de.Highlight, offset, 3)
-
- var buf strings.Builder
+ if de == nil {
+ return nil
+ }
+ return newDecodeError(document, de.Highlight, de.Key, de.Message)
+}
- maxLine := errLine + len(after) - 1
- lineColumnWidth := len(strconv.Itoa(maxLine))
+// newDecodeError creates a DecodeError pointing at the given highlight, which
+// needs to be a subslice of the document.
+func newDecodeError(document []byte, highlight []byte, key Key, message string) *DecodeError {
+ offset := subsliceOffset(document, highlight)
- // Write the lines of context strictly before the error.
- for i := len(before) - 1; i > 0; i-- {
- line := errLine - i
- buf.WriteString(formatLineNumber(line, lineColumnWidth))
- buf.WriteString("|")
+ errLineIdx, errColumn := positionAt(document, offset)
- if len(before[i]) > 0 {
- buf.WriteString(" ")
- buf.Write(before[i])
- }
+ human := buildHumanContext(document, errLineIdx, errColumn, len(highlight), message)
- buf.WriteRune('\n')
+ return &DecodeError{
+ message: message,
+ line: errLineIdx + 1,
+ column: errColumn,
+ key: key,
+ human: human,
}
+}
- // Write the document line that contains the error.
-
- buf.WriteString(formatLineNumber(errLine, lineColumnWidth))
- buf.WriteString("| ")
-
- if len(before) > 0 {
- buf.Write(before[0])
+// subsliceOffset returns the offset of the subslice b within the document.
+func subsliceOffset(document, b []byte) int {
+ // Highlights are subslices of the document, which means they share the
+ // same backing array, and their capacity counts the bytes between their
+ // start and the end of the backing array.
+ offset := cap(document) - cap(b)
+ if offset < 0 || offset+len(b) > len(document) {
+ panic(errors.New("highlight is not a subslice of the document"))
}
+ return offset
+}
- buf.Write(de.Highlight)
-
- if len(after) > 0 {
- buf.Write(after[0])
+// positionAt returns the 0-indexed line and the 1-indexed column of the given
+// offset in the document.
+func positionAt(document []byte, offset int) (lineIdx int, column int) {
+ lineStart := 0
+ for i := 0; i < offset; i++ {
+ if document[i] == '\n' {
+ lineIdx++
+ lineStart = i + 1
+ }
}
+ return lineIdx, offset - lineStart + 1
+}
- buf.WriteRune('\n')
-
- // Write the line with the error message itself (so it does not have a line
- // number).
-
- buf.WriteString(strings.Repeat(" ", lineColumnWidth))
- buf.WriteString("| ")
-
- if len(before) > 0 {
- buf.WriteString(strings.Repeat(" ", len(before[0])))
+// docLines splits the document into lines, removing the trailing newline
+// characters.
+func docLines(document []byte) []string {
+ s := string(document)
+ lines := strings.Split(s, "\n")
+ for i, l := range lines {
+ lines[i] = strings.TrimSuffix(l, "\r")
}
+ return lines
+}
- buf.WriteString(strings.Repeat("~", len(de.Highlight)))
+// buildHumanContext renders the human-readable multi-line context of an
+// error: a window of up to 3 lines before and after the error line, with
+// the error position underlined.
+func buildHumanContext(document []byte, errLineIdx, errColumn, highlightLen int, message string) string {
+ lines := docLines(document)
- if len(errMessage) > 0 {
- buf.WriteString(" ")
- buf.WriteString(errMessage)
+ const window = 3
+ firstIdx := errLineIdx - window
+ if firstIdx < 0 {
+ firstIdx = 0
}
-
- // Write the lines of context strictly after the error.
-
- for i := 1; i < len(after); i++ {
- buf.WriteRune('\n')
- line := errLine + i
- buf.WriteString(formatLineNumber(line, lineColumnWidth))
- buf.WriteString("|")
-
- if len(after[i]) > 0 {
- buf.WriteString(" ")
- buf.Write(after[i])
- }
+ lastIdx := errLineIdx + window
+ if lastIdx > len(lines)-1 {
+ lastIdx = len(lines) - 1
}
-
- return &DecodeError{
- message: errMessage,
- line: errLine,
- column: errColumn,
- key: de.Key,
- human: buf.String(),
+ // Empty lines at the edges of the window are dropped, unless the error
+ // is about that very position.
+ for firstIdx < errLineIdx && lines[firstIdx] == "" {
+ firstIdx++
+ }
+ for lastIdx > errLineIdx && lines[lastIdx] == "" {
+ lastIdx--
}
-}
-func formatLineNumber(line int, width int) string {
- format := "%" + strconv.Itoa(width) + "d"
+ // Width of the column of line numbers.
+ width := len(strconv.Itoa(lastIdx + 1))
- return fmt.Sprintf(format, line)
-}
-
-func linesOfContext(document []byte, highlight []byte, offset int, linesAround int) ([][]byte, [][]byte) {
- return beforeLines(document, offset, linesAround), afterLines(document, highlight, offset, linesAround)
-}
+ var buf strings.Builder
-func beforeLines(document []byte, offset int, linesAround int) [][]byte {
- var beforeLines [][]byte
-
- // Walk the document backward from the highlight to find previous lines
- // of context.
- rest := document[:offset]
-backward:
- for o := len(rest) - 1; o >= 0 && len(beforeLines) <= linesAround && len(rest) > 0; {
- switch {
- case rest[o] == '\n':
- // handle individual lines
- beforeLines = append(beforeLines, rest[o+1:])
- rest = rest[:o]
- o = len(rest) - 1
- case o == 0:
- // add the first line only if it's non-empty
- beforeLines = append(beforeLines, rest)
-
- break backward
- default:
- o--
+ writeLine := func(idx int) {
+ number := strconv.Itoa(idx + 1)
+ for i := len(number); i < width; i++ {
+ buf.WriteByte(' ')
}
+ buf.WriteString(number)
+ buf.WriteByte('|')
+ if len(lines[idx]) > 0 {
+ buf.WriteByte(' ')
+ buf.WriteString(lines[idx])
+ }
+ buf.WriteByte('\n')
}
- return beforeLines
-}
+ for idx := firstIdx; idx <= errLineIdx; idx++ {
+ writeLine(idx)
+ }
-func afterLines(document []byte, highlight []byte, offset int, linesAround int) [][]byte {
- var afterLines [][]byte
-
- // Walk the document forward from the highlight to find the following
- // lines of context.
- rest := document[offset+len(highlight):]
-forward:
- for o := 0; o < len(rest) && len(afterLines) <= linesAround; {
- switch {
- case rest[o] == '\n':
- // handle individual lines
- afterLines = append(afterLines, rest[:o])
- rest = rest[o+1:]
- o = 0
-
- case o == len(rest)-1:
- // add last line only if it's non-empty
- afterLines = append(afterLines, rest)
-
- break forward
- default:
- o++
+ // Underline the error.
+ for i := 0; i < width; i++ {
+ buf.WriteByte(' ')
+ }
+ buf.WriteString("| ")
+ for i := 1; i < errColumn; i++ {
+ buf.WriteByte(' ')
+ }
+ // The highlight cannot extend past the end of its line.
+ tildes := highlightLen
+ if errLineIdx < len(lines) {
+ if avail := len(lines[errLineIdx]) - errColumn + 1; tildes > avail {
+ tildes = avail
}
}
+ if tildes < 1 {
+ tildes = 1
+ }
+ for i := 0; i < tildes; i++ {
+ buf.WriteByte('~')
+ }
+ if message != "" {
+ buf.WriteByte(' ')
+ buf.WriteString(message)
+ }
+ buf.WriteByte('\n')
- return afterLines
-}
-
-func positionAtEnd(b []byte) (row int, column int) {
- row = 1
- column = 1
-
- for _, c := range b {
- if c == '\n' {
- row++
- column = 1
- } else {
- column++
- }
+ for idx := errLineIdx + 1; idx <= lastIdx; idx++ {
+ writeLine(idx)
}
- return
+ return strings.TrimSuffix(buf.String(), "\n")
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go b/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go
deleted file mode 100644
index 80f698db..00000000
--- a/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package characters
-
-var invalidAsciiTable = [256]bool{
- 0x00: true,
- 0x01: true,
- 0x02: true,
- 0x03: true,
- 0x04: true,
- 0x05: true,
- 0x06: true,
- 0x07: true,
- 0x08: true,
- // 0x09 TAB
- // 0x0A LF
- 0x0B: true,
- 0x0C: true,
- // 0x0D CR
- 0x0E: true,
- 0x0F: true,
- 0x10: true,
- 0x11: true,
- 0x12: true,
- 0x13: true,
- 0x14: true,
- 0x15: true,
- 0x16: true,
- 0x17: true,
- 0x18: true,
- 0x19: true,
- 0x1A: true,
- 0x1B: true,
- 0x1C: true,
- 0x1D: true,
- 0x1E: true,
- 0x1F: true,
- // 0x20 - 0x7E Printable ASCII characters
- 0x7F: true,
-}
-
-func InvalidAscii(b byte) bool {
- return invalidAsciiTable[b]
-}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go b/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go
deleted file mode 100644
index db4f45ac..00000000
--- a/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go
+++ /dev/null
@@ -1,199 +0,0 @@
-package characters
-
-import (
- "unicode/utf8"
-)
-
-type utf8Err struct {
- Index int
- Size int
-}
-
-func (u utf8Err) Zero() bool {
- return u.Size == 0
-}
-
-// Verified that a given string is only made of valid UTF-8 characters allowed
-// by the TOML spec:
-//
-// Any Unicode character may be used except those that must be escaped:
-// quotation mark, backslash, and the control characters other than tab (U+0000
-// to U+0008, U+000A to U+001F, U+007F).
-//
-// It is a copy of the Go 1.17 utf8.Valid implementation, tweaked to exit early
-// when a character is not allowed.
-//
-// The returned utf8Err is Zero() if the string is valid, or contains the byte
-// index and size of the invalid character.
-//
-// quotation mark => already checked
-// backslash => already checked
-// 0-0x8 => invalid
-// 0x9 => tab, ok
-// 0xA - 0x1F => invalid
-// 0x7F => invalid
-func Utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
- // Fast path. Check for and skip 8 bytes of ASCII characters per iteration.
- offset := 0
- for len(p) >= 8 {
- // Combining two 32 bit loads allows the same code to be used
- // for 32 and 64 bit platforms.
- // The compiler can generate a 32bit load for first32 and second32
- // on many platforms. See test/codegen/memcombine.go.
- first32 := uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
- second32 := uint32(p[4]) | uint32(p[5])<<8 | uint32(p[6])<<16 | uint32(p[7])<<24
- if (first32|second32)&0x80808080 != 0 {
- // Found a non ASCII byte (>= RuneSelf).
- break
- }
-
- for i, b := range p[:8] {
- if InvalidAscii(b) {
- err.Index = offset + i
- err.Size = 1
- return
- }
- }
-
- p = p[8:]
- offset += 8
- }
- n := len(p)
- for i := 0; i < n; {
- pi := p[i]
- if pi < utf8.RuneSelf {
- if InvalidAscii(pi) {
- err.Index = offset + i
- err.Size = 1
- return
- }
- i++
- continue
- }
- x := first[pi]
- if x == xx {
- // Illegal starter byte.
- err.Index = offset + i
- err.Size = 1
- return
- }
- size := int(x & 7)
- if i+size > n {
- // Short or invalid.
- err.Index = offset + i
- err.Size = n - i
- return
- }
- accept := acceptRanges[x>>4]
- if c := p[i+1]; c < accept.lo || accept.hi < c {
- err.Index = offset + i
- err.Size = 2
- return
- } else if size == 2 {
- } else if c := p[i+2]; c < locb || hicb < c {
- err.Index = offset + i
- err.Size = 3
- return
- } else if size == 3 {
- } else if c := p[i+3]; c < locb || hicb < c {
- err.Index = offset + i
- err.Size = 4
- return
- }
- i += size
- }
- return
-}
-
-// Return the size of the next rune if valid, 0 otherwise.
-func Utf8ValidNext(p []byte) int {
- c := p[0]
-
- if c < utf8.RuneSelf {
- if InvalidAscii(c) {
- return 0
- }
- return 1
- }
-
- x := first[c]
- if x == xx {
- // Illegal starter byte.
- return 0
- }
- size := int(x & 7)
- if size > len(p) {
- // Short or invalid.
- return 0
- }
- accept := acceptRanges[x>>4]
- if c := p[1]; c < accept.lo || accept.hi < c {
- return 0
- } else if size == 2 {
- } else if c := p[2]; c < locb || hicb < c {
- return 0
- } else if size == 3 {
- } else if c := p[3]; c < locb || hicb < c {
- return 0
- }
-
- return size
-}
-
-// acceptRange gives the range of valid values for the second byte in a UTF-8
-// sequence.
-type acceptRange struct {
- lo uint8 // lowest value for second byte.
- hi uint8 // highest value for second byte.
-}
-
-// acceptRanges has size 16 to avoid bounds checks in the code that uses it.
-var acceptRanges = [16]acceptRange{
- 0: {locb, hicb},
- 1: {0xA0, hicb},
- 2: {locb, 0x9F},
- 3: {0x90, hicb},
- 4: {locb, 0x8F},
-}
-
-// first is information about the first byte in a UTF-8 sequence.
-var first = [256]uint8{
- // 1 2 3 4 5 6 7 8 9 A B C D E F
- as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F
- as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F
- as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F
- as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F
- as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F
- as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F
- as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F
- as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F
- // 1 2 3 4 5 6 7 8 9 A B C D E F
- xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F
- xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F
- xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF
- xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF
- xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF
- s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF
- s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF
- s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
-}
-
-const (
- // The default lowest and highest continuation byte.
- locb = 0b10000000
- hicb = 0b10111111
-
- // These names of these constants are chosen to give nice alignment in the
- // table below. The first nibble is an index into acceptRanges or F for
- // special one-byte cases. The second nibble is the Rune length or the
- // Status for the special one-byte case.
- xx = 0xF1 // invalid: size 1
- as = 0xF0 // ASCII: size 1
- s1 = 0x02 // accept 0, size 2
- s2 = 0x13 // accept 1, size 3
- s3 = 0x03 // accept 0, size 3
- s4 = 0x23 // accept 2, size 3
- s5 = 0x34 // accept 3, size 4
- s6 = 0x04 // accept 0, size 4
- s7 = 0x44 // accept 4, size 4
-)
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go b/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go
deleted file mode 100644
index e38e1131..00000000
--- a/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package danger
-
-import (
- "fmt"
- "reflect"
- "unsafe"
-)
-
-const maxInt = uintptr(int(^uint(0) >> 1))
-
-func SubsliceOffset(data []byte, subslice []byte) int {
- datap := (*reflect.SliceHeader)(unsafe.Pointer(&data))
- hlp := (*reflect.SliceHeader)(unsafe.Pointer(&subslice))
-
- if hlp.Data < datap.Data {
- panic(fmt.Errorf("subslice address (%d) is before data address (%d)", hlp.Data, datap.Data))
- }
- offset := hlp.Data - datap.Data
-
- if offset > maxInt {
- panic(fmt.Errorf("slice offset larger than int (%d)", offset))
- }
-
- intoffset := int(offset)
-
- if intoffset > datap.Len {
- panic(fmt.Errorf("slice offset (%d) is farther than data length (%d)", intoffset, datap.Len))
- }
-
- if intoffset+hlp.Len > datap.Len {
- panic(fmt.Errorf("slice ends (%d+%d) is farther than data length (%d)", intoffset, hlp.Len, datap.Len))
- }
-
- return intoffset
-}
-
-func BytesRange(start []byte, end []byte) []byte {
- if start == nil || end == nil {
- panic("cannot call BytesRange with nil")
- }
- startp := (*reflect.SliceHeader)(unsafe.Pointer(&start))
- endp := (*reflect.SliceHeader)(unsafe.Pointer(&end))
-
- if startp.Data > endp.Data {
- panic(fmt.Errorf("start pointer address (%d) is after end pointer address (%d)", startp.Data, endp.Data))
- }
-
- l := startp.Len
- endLen := int(endp.Data-startp.Data) + endp.Len
- if endLen > l {
- l = endLen
- }
-
- if l > startp.Cap {
- panic(fmt.Errorf("range length is larger than capacity"))
- }
-
- return start[:l]
-}
-
-func Stride(ptr unsafe.Pointer, size uintptr, offset int) unsafe.Pointer {
- // TODO: replace with unsafe.Add when Go 1.17 is released
- // https://github.com/golang/go/issues/40481
- return unsafe.Pointer(uintptr(ptr) + uintptr(int(size)*offset))
-}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go b/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go
deleted file mode 100644
index 9d41c28a..00000000
--- a/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package danger
-
-import (
- "reflect"
- "unsafe"
-)
-
-// typeID is used as key in encoder and decoder caches to enable using
-// the optimize runtime.mapaccess2_fast64 function instead of the more
-// expensive lookup if we were to use reflect.Type as map key.
-//
-// typeID holds the pointer to the reflect.Type value, which is unique
-// in the program.
-//
-// https://github.com/segmentio/encoding/blob/master/json/codec.go#L59-L61
-type TypeID unsafe.Pointer
-
-func MakeTypeID(t reflect.Type) TypeID {
- // reflect.Type has the fields:
- // typ unsafe.Pointer
- // ptr unsafe.Pointer
- return TypeID((*[2]unsafe.Pointer)(unsafe.Pointer(&t))[1])
-}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/parserbridge/parserbridge.go b/vendor/github.com/pelletier/go-toml/v2/internal/parserbridge/parserbridge.go
new file mode 100644
index 00000000..703aceea
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/parserbridge/parserbridge.go
@@ -0,0 +1,37 @@
+// Package parserbridge exposes the unstable parser's non-AST scanners to the
+// root toml package without making them part of the unstable public API.
+//
+// The fused generic-decode fast path needs to scan keys, scalars and comments
+// (and parse container values into the arena) without going through the
+// AST-pushing NextExpression/Expression methods. Those scanners depend on
+// Parser internals (the string-unescape scratch buffer and the node arena), so
+// they have to live in the unstable package; but they are an implementation
+// detail of the decoder, not something we want to commit to in the public API.
+//
+// The unstable package populates these variables in its init; the toml package
+// reads them. The parser is passed as an any (it is always an *unstable.Parser)
+// and the scalar kind is an int (it is always an unstable.Kind) so that this
+// package imports neither unstable nor toml, avoiding an import cycle. Passing
+// a pointer through an interface does not allocate, so the fused path keeps its
+// allocation profile.
+package parserbridge
+
+var (
+ // ScanScalar scans a single scalar value (string, integer, float, bool or
+ // date/time) without building an AST node. kind is an unstable.Kind.
+ ScanScalar func(p any, b []byte) (kind int, raw, value, rest []byte, err error)
+
+ // ScanKey scans a (possibly dotted) key without building AST nodes,
+ // appending each decoded part to dst.
+ ScanKey func(p any, b []byte, dst [][]byte) (parts [][]byte, raw, rest []byte, err error)
+
+ // ScanComment scans a comment starting at '#', returning the comment bytes
+ // (including '#', excluding the line ending) and the rest of the input. It
+ // needs no parser state.
+ ScanComment func(b []byte) (comment, rest []byte, err error)
+
+ // ParseValue parses a single value (including arrays and inline tables) into
+ // the parser arena, returning the root *unstable.Node and the rest of the
+ // input.
+ ParseValue func(p any, b []byte) (node any, rest []byte, err error)
+)
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
index 149b17f5..661b11cf 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
@@ -14,7 +14,8 @@ func (t *KeyTracker) UpdateTable(node *unstable.Node) {
t.Push(node)
}
-// UpdateArrayTable sets the state of the tracker with the AST array table node.
+// UpdateArrayTable sets the state of the tracker with the AST array table
+// node.
func (t *KeyTracker) UpdateArrayTable(node *unstable.Node) {
t.reset()
t.Push(node)
@@ -36,7 +37,7 @@ func (t *KeyTracker) Pop(node *unstable.Node) {
}
}
-// Key returns the current key
+// Key returns the current key.
func (t *KeyTracker) Key() []string {
k := make([]string, len(t.k))
copy(k, t.k)
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
index 76df2d5b..e88cd941 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
@@ -3,7 +3,6 @@ package tracker
import (
"bytes"
"fmt"
- "sync"
"github.com/pelletier/go-toml/v2/unstable"
)
@@ -12,9 +11,21 @@ type keyKind uint8
const (
invalidKind keyKind = iota
+ // valueKind is a regular value (scalar, array, or inline table). It
+ // cannot be extended.
valueKind
+ // kvTableKind is a table created implicitly by a dotted key. It can only
+ // be extended by other dotted keys.
+ kvTableKind
+ // tableKind is a table created by a [header]. The explicit flag tells
+ // whether the table was created by its own header (true) or as an
+ // intermediate step of a longer key (false).
tableKind
+ // arrayTableKind is an array of tables created by [[header]].
arrayTableKind
+ // anonymousKind is an entry that cannot be looked up by name. It serves
+ // as the parent of the content of inline tables stored inside arrays.
+ anonymousKind
)
func (k keyKind) String() string {
@@ -23,22 +34,36 @@ func (k keyKind) String() string {
return "invalid"
case valueKind:
return "value"
+ case kvTableKind:
+ return "kv-table"
case tableKind:
return "table"
case arrayTableKind:
- return "array table"
+ return "array-table"
+ case anonymousKind:
+ return "anonymous"
}
panic("missing keyKind string mapping")
}
+// entry represents a node that has been seen in the document. Its size has a
+// direct impact on the performance of unmarshaling documents: keep it as
+// small as possible.
+type entry struct {
+ parent int32
+ kind keyKind
+ explicit bool
+ name []byte
+}
+
// SeenTracker tracks which keys have been seen with which TOML type to flag
// duplicates and mismatches according to the spec.
//
-// Each node in the visited tree is represented by an entry. Each entry has an
-// identifier, which is provided by a counter. Entries are stored in the array
-// entries. As new nodes are discovered (referenced for the first time in the
-// TOML document), entries are created and appended to the array. An entry
-// points to its parent using its id.
+// Each node in the visited tree is represented by an entry. Each entry has
+// an identifier, which is provided by a counter. Entries are stored in the
+// array entries. As new nodes are discovered (referenced for the first time
+// in the TOML document), entries are created and appended to the array. An
+// entry points to its parent using its id.
//
// To find whether a given key (sequence of []byte) has already been visited,
// the entries are linearly searched, looking for one with the right name and
@@ -53,306 +78,373 @@ func (k keyKind) String() string {
// invariant above, the deletion process needs to keep the order of entries.
// This results in more copies in that case.
type SeenTracker struct {
- entries []entry
- currentIdx int
-}
+ entries []entry
+ currentTable int32
-var pool = sync.Pool{
- New: func() interface{} {
- return &SeenTracker{}
- },
+ // scratch buffers for clear()
+ removedBuf []bool
+ remapBuf []int32
}
-func (s *SeenTracker) reset() {
- // Always contains a root element at index 0.
- s.currentIdx = 0
- if len(s.entries) == 0 {
- s.entries = make([]entry, 1, 2)
- } else {
- s.entries = s.entries[:1]
- }
- s.entries[0].child = -1
- s.entries[0].next = -1
+// Reset brings the tracker to its initial state, with just a root table, so
+// that it can be reused across documents.
+func (s *SeenTracker) Reset() {
+ s.reset()
}
-type entry struct {
- // Use -1 to indicate no child or no sibling.
- child int
- next int
-
- name []byte
- kind keyKind
- explicit bool
- kv bool
+// reset brings the tracker to its initial state, with just a root table.
+func (s *SeenTracker) reset() {
+ s.entries = append(s.entries[:0], entry{
+ parent: -1,
+ kind: tableKind,
+ })
+ s.currentTable = 0
}
-// Find the index of the child of parentIdx with key k. Returns -1 if
-// it does not exist.
-func (s *SeenTracker) find(parentIdx int, k []byte) int {
- for i := s.entries[parentIdx].child; i >= 0; i = s.entries[i].next {
- if bytes.Equal(s.entries[i].name, k) {
- return i
+// find returns the id of the entry with the given parent and name, or -1.
+// Anonymous entries are never returned.
+func (s *SeenTracker) find(parent int32, name []byte) int32 {
+ // Children always appear after their parent.
+ for i := int(parent) + 1; i < len(s.entries); i++ {
+ e := &s.entries[i]
+ if e.parent == parent && e.kind != anonymousKind && bytes.Equal(e.name, name) {
+ return int32(i) //nolint:gosec // entry counts are bounded by document size
}
}
return -1
}
-// Remove all descendants of node at position idx.
-func (s *SeenTracker) clear(idx int) {
- if idx >= len(s.entries) {
- return
- }
-
- for i := s.entries[idx].child; i >= 0; {
- next := s.entries[i].next
- n := s.entries[0].next
- s.entries[0].next = i
- s.entries[i].next = n
- s.entries[i].name = nil
- s.clear(i)
- i = next
- }
-
- s.entries[idx].child = -1
-}
-
-func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit bool, kv bool) int {
- e := entry{
- child: -1,
- next: s.entries[parentIdx].child,
-
- name: name,
+// create appends a new entry and returns its id.
+func (s *SeenTracker) create(parent int32, name []byte, kind keyKind, explicit bool) int32 {
+ id := int32(len(s.entries)) //nolint:gosec // entry counts are bounded by document size
+ s.entries = append(s.entries, entry{
+ parent: parent,
kind: kind,
explicit: explicit,
- kv: kv,
+ name: name,
+ })
+ return id
+}
+
+// clear removes all the descendants of the entry with the given id, keeping
+// the order of the remaining entries.
+func (s *SeenTracker) clear(id int32) {
+ // Compute which entries are removed. Given that children always appear
+ // after their parent, a single forward pass is enough.
+ if cap(s.removedBuf) < len(s.entries) {
+ s.removedBuf = make([]bool, len(s.entries))
+ s.remapBuf = make([]int32, len(s.entries))
}
- var idx int
- if s.entries[0].next >= 0 {
- idx = s.entries[0].next
- s.entries[0].next = s.entries[idx].next
- s.entries[idx] = e
- } else {
- idx = len(s.entries)
- s.entries = append(s.entries, e)
+ removed := s.removedBuf[:len(s.entries)]
+ remap := s.remapBuf[:len(s.entries)]
+ for i := range removed {
+ removed[i] = false
}
- s.entries[parentIdx].child = idx
-
- return idx
-}
-
-func (s *SeenTracker) setExplicitFlag(parentIdx int) {
- for i := s.entries[parentIdx].child; i >= 0; i = s.entries[i].next {
- if s.entries[i].kv {
- s.entries[i].explicit = true
- s.entries[i].kv = false
+ n := int32(0)
+ for i := 0; i < len(s.entries); i++ {
+ parent := s.entries[i].parent
+ if parent >= 0 && (parent == id && s.entries[i].kind != invalidKind || removed[parent]) {
+ removed[i] = true
+ continue
}
- s.setExplicitFlag(i)
+ remap[i] = n
+ if int32(i) != n { //nolint:gosec // entry counts are bounded by document size
+ e := s.entries[i]
+ e.parent = remap[e.parent]
+ s.entries[n] = e
+ }
+ n++
}
+ s.entries = s.entries[:n]
}
// CheckExpression takes a top-level node and checks that it does not contain
// keys that have been seen in previous calls, and validates that types are
-// consistent. It returns true if it is the first time this node's key is seen.
-// Useful to clear array tables on first use.
+// consistent. It returns true if it is the first time this node's key is
+// seen. Useful to clear array tables on first use.
func (s *SeenTracker) CheckExpression(node *unstable.Node) (bool, error) {
- if s.entries == nil {
+ if len(s.entries) == 0 {
s.reset()
}
switch node.Kind {
case unstable.KeyValue:
- return s.checkKeyValue(node)
+ return false, s.checkKeyValue(s.currentTable, node)
case unstable.Table:
return s.checkTable(node)
case unstable.ArrayTable:
return s.checkArrayTable(node)
default:
- panic(fmt.Errorf("this should not be a top level node type: %s", node.Kind))
+ return false, fmt.Errorf("toml: unexpected expression kind %s", node.Kind)
}
}
-func (s *SeenTracker) checkTable(node *unstable.Node) (bool, error) {
- if s.currentIdx >= 0 {
- s.setExplicitFlag(s.currentIdx)
- }
-
- it := node.Key()
-
- parentIdx := 0
-
- // This code is duplicated in checkArrayTable. This is because factoring
- // it in a function requires to copy the iterator, or allocate it to the
- // heap, which is not cheap.
- for it.Next() {
- if it.IsLast() {
- break
+// CheckTable validates a [table] header given the decoded parts of its key.
+// It mirrors checkTable but is driven directly from the key parts instead of
+// an AST, for callers that decode without building one. It returns whether the
+// table is seen for the first time.
+func (s *SeenTracker) CheckTable(parts [][]byte) (bool, error) {
+ parent := int32(0)
+ for k := 0; k < len(parts); k++ {
+ name := parts[k]
+ if k == len(parts)-1 {
+ // Final part of the key.
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, tableKind, true)
+ s.currentTable = i
+ return true, nil
+ }
+ e := &s.entries[i]
+ switch e.kind {
+ case tableKind:
+ if e.explicit {
+ return false, fmt.Errorf("toml: table %s already exists", name)
+ }
+ e.explicit = true
+ s.currentTable = i
+ return false, nil
+ case kvTableKind:
+ return false, fmt.Errorf("toml: table %s already exists as defined by a dotted key", name)
+ case arrayTableKind:
+ return false, fmt.Errorf("toml: table %s already exists as an array of tables", name)
+ default:
+ return false, fmt.Errorf("toml: key %s should be a table, not a %s", name, e.kind)
+ }
}
- k := it.Node().Data
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, tableKind, false)
+ } else {
+ switch s.entries[i].kind {
+ case tableKind, arrayTableKind, kvTableKind:
+ // Tables created by dotted keys can receive new sub-tables,
+ // but cannot be redefined (handled by the last-part case).
+ default:
+ return false, fmt.Errorf("toml: key %s already exists as a value", name)
+ }
+ }
+ parent = i
+ }
+ panic("unreachable: table expression without key")
+}
- idx := s.find(parentIdx, k)
+// CheckArrayTable validates a [[array table]] header given the decoded parts
+// of its key. It mirrors checkArrayTable but is driven directly from the key
+// parts. It returns whether the array table is seen for the first time.
+func (s *SeenTracker) CheckArrayTable(parts [][]byte) (bool, error) {
+ parent := int32(0)
+ for k := 0; k < len(parts); k++ {
+ name := parts[k]
+ if k == len(parts)-1 {
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, arrayTableKind, true)
+ s.currentTable = i
+ return true, nil
+ }
+ if s.entries[i].kind != arrayTableKind {
+ return false, fmt.Errorf("toml: key %s already exists as a %s, but should be an array table", name, s.entries[i].kind)
+ }
+ // Make the descendants of this array table re-discoverable for
+ // the new element.
+ s.clear(i)
+ s.currentTable = i
+ return false, nil
+ }
- if idx < 0 {
- idx = s.create(parentIdx, k, tableKind, false, false)
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, tableKind, false)
} else {
- entry := s.entries[idx]
- if entry.kind == valueKind {
- return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
+ switch s.entries[i].kind {
+ case tableKind, arrayTableKind, kvTableKind:
+ // Tables created by dotted keys can receive new sub-tables,
+ // but cannot be redefined (handled by the last-part case).
+ default:
+ return false, fmt.Errorf("toml: key %s already exists as a value", name)
}
}
- parentIdx = idx
+ parent = i
}
+ panic("unreachable: array table expression without key")
+}
- k := it.Node().Data
- idx := s.find(parentIdx, k)
-
- first := false
- if idx >= 0 {
- kind := s.entries[idx].kind
- if kind != tableKind {
- return false, fmt.Errorf("toml: key %s should be a table, not a %s", string(k), kind)
+// CheckKeyValue validates the (possibly dotted) key of a key-value under the
+// current table, WITHOUT validating its value. It returns the id of the leaf
+// entry, so the caller can validate a container value with CheckValueUnder.
+func (s *SeenTracker) CheckKeyValue(parts [][]byte) (int32, error) {
+ parent := s.currentTable
+ for k := 0; k < len(parts); k++ {
+ name := parts[k]
+ if k == len(parts)-1 {
+ if i := s.find(parent, name); i >= 0 {
+ return -1, fmt.Errorf("toml: key %s is already defined", name)
+ }
+ return s.create(parent, name, valueKind, false), nil
}
- if s.entries[idx].explicit {
- return false, fmt.Errorf("toml: table %s already exists", string(k))
+
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, kvTableKind, false)
+ } else if s.entries[i].kind != kvTableKind {
+ return -1, fmt.Errorf("toml: key %s is already defined", name)
}
- s.entries[idx].explicit = true
- } else {
- idx = s.create(parentIdx, k, tableKind, true, false)
- first = true
+ parent = i
}
+ panic("unreachable: key-value expression without key")
+}
- s.currentIdx = idx
-
- return first, nil
+// CheckValueUnder validates the content of a value stored under the given
+// entry (typically the leaf returned by CheckKeyValue): inline tables cannot
+// contain duplicate keys, including in the inline tables and arrays they
+// contain.
+func (s *SeenTracker) CheckValueUnder(parent int32, value *unstable.Node) error {
+ return s.checkValue(parent, value)
}
-func (s *SeenTracker) checkArrayTable(node *unstable.Node) (bool, error) {
- if s.currentIdx >= 0 {
- s.setExplicitFlag(s.currentIdx)
- }
+func (s *SeenTracker) checkTable(node *unstable.Node) (bool, error) {
+ parent := int32(0)
it := node.Key()
-
- parentIdx := 0
-
+ // Handle the intermediate parts of the key.
for it.Next() {
+ part := it.Node()
+ name := part.Data
if it.IsLast() {
- break
+ // Final part of the key.
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, tableKind, true)
+ s.currentTable = i
+ return true, nil
+ }
+ e := &s.entries[i]
+ switch e.kind {
+ case tableKind:
+ if e.explicit {
+ return false, fmt.Errorf("toml: table %s already exists", name)
+ }
+ e.explicit = true
+ s.currentTable = i
+ return false, nil
+ case kvTableKind:
+ return false, fmt.Errorf("toml: table %s already exists as defined by a dotted key", name)
+ case arrayTableKind:
+ return false, fmt.Errorf("toml: table %s already exists as an array of tables", name)
+ default:
+ return false, fmt.Errorf("toml: key %s should be a table, not a %s", name, e.kind)
+ }
}
- k := it.Node().Data
-
- idx := s.find(parentIdx, k)
-
- if idx < 0 {
- idx = s.create(parentIdx, k, tableKind, false, false)
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, tableKind, false)
} else {
- entry := s.entries[idx]
- if entry.kind == valueKind {
- return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
+ switch s.entries[i].kind {
+ case tableKind, arrayTableKind, kvTableKind:
+ // Tables created by dotted keys can receive new sub-tables,
+ // but cannot be redefined (handled by the last-part case).
+ default:
+ return false, fmt.Errorf("toml: key %s already exists as a value", name)
}
}
-
- parentIdx = idx
+ parent = i
}
-
- k := it.Node().Data
- idx := s.find(parentIdx, k)
-
- firstTime := idx < 0
- if firstTime {
- idx = s.create(parentIdx, k, arrayTableKind, true, false)
- } else {
- kind := s.entries[idx].kind
- if kind != arrayTableKind {
- return false, fmt.Errorf("toml: key %s already exists as a %s, but should be an array table", kind, string(k))
- }
- s.clear(idx)
- }
-
- s.currentIdx = idx
-
- return firstTime, nil
+ panic("unreachable: table expression without key")
}
-func (s *SeenTracker) checkKeyValue(node *unstable.Node) (bool, error) {
- parentIdx := s.currentIdx
- it := node.Key()
+func (s *SeenTracker) checkArrayTable(node *unstable.Node) (bool, error) {
+ parent := int32(0)
+ it := node.Key()
for it.Next() {
- k := it.Node().Data
-
- idx := s.find(parentIdx, k)
+ part := it.Node()
+ name := part.Data
+ if it.IsLast() {
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, arrayTableKind, true)
+ s.currentTable = i
+ return true, nil
+ }
+ if s.entries[i].kind != arrayTableKind {
+ return false, fmt.Errorf("toml: key %s already exists as a %s, but should be an array table", name, s.entries[i].kind)
+ }
+ // Make the descendants of this array table re-discoverable for
+ // the new element.
+ s.clear(i)
+ // Note: clear cannot move i because i comes before all its
+ // descendants.
+ s.currentTable = i
+ return false, nil
+ }
- if idx < 0 {
- idx = s.create(parentIdx, k, tableKind, false, true)
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, tableKind, false)
} else {
- entry := s.entries[idx]
- if it.IsLast() {
- return false, fmt.Errorf("toml: key %s is already defined", string(k))
- } else if entry.kind != tableKind {
- return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
- } else if entry.explicit {
- return false, fmt.Errorf("toml: cannot redefine table %s that has already been explicitly defined", string(k))
+ switch s.entries[i].kind {
+ case tableKind, arrayTableKind, kvTableKind:
+ // Tables created by dotted keys can receive new sub-tables,
+ // but cannot be redefined (handled by the last-part case).
+ default:
+ return false, fmt.Errorf("toml: key %s already exists as a value", name)
}
}
-
- parentIdx = idx
+ parent = i
}
-
- s.entries[parentIdx].kind = valueKind
-
- value := node.Value()
-
- switch value.Kind {
- case unstable.InlineTable:
- return s.checkInlineTable(value)
- case unstable.Array:
- return s.checkArray(value)
- }
-
- return false, nil
+ panic("unreachable: array table expression without key")
}
-func (s *SeenTracker) checkArray(node *unstable.Node) (first bool, err error) {
- it := node.Children()
+func (s *SeenTracker) checkKeyValue(parent int32, node *unstable.Node) error {
+ it := node.Key()
for it.Next() {
- n := it.Node()
- switch n.Kind {
- case unstable.InlineTable:
- first, err = s.checkInlineTable(n)
- if err != nil {
- return false, err
- }
- case unstable.Array:
- first, err = s.checkArray(n)
- if err != nil {
- return false, err
+ part := it.Node()
+ name := part.Data
+ if it.IsLast() {
+ if i := s.find(parent, name); i >= 0 {
+ return fmt.Errorf("toml: key %s is already defined", name)
}
+ id := s.create(parent, name, valueKind, false)
+ return s.checkValue(id, node.Value())
}
+
+ i := s.find(parent, name)
+ if i < 0 {
+ i = s.create(parent, name, kvTableKind, false)
+ } else if s.entries[i].kind != kvTableKind {
+ return fmt.Errorf("toml: key %s is already defined", name)
+ }
+ parent = i
}
- return first, nil
+ panic("unreachable: key-value expression without key")
}
-func (s *SeenTracker) checkInlineTable(node *unstable.Node) (first bool, err error) {
- s = pool.Get().(*SeenTracker)
- s.reset()
-
- it := node.Children()
- for it.Next() {
- n := it.Node()
- first, err = s.checkKeyValue(n)
- if err != nil {
- return false, err
+// checkValue verifies the content of a value: inline tables cannot contain
+// duplicate keys, including in the inline tables and arrays they contain.
+func (s *SeenTracker) checkValue(id int32, value *unstable.Node) error {
+ switch value.Kind {
+ case unstable.InlineTable:
+ it := value.Children()
+ for it.Next() {
+ if err := s.checkKeyValue(id, it.Node()); err != nil {
+ return err
+ }
+ }
+ case unstable.Array:
+ it := value.Children()
+ for it.Next() {
+ elem := it.Node()
+ if elem.Kind == unstable.InlineTable || elem.Kind == unstable.Array {
+ elemID := s.create(id, nil, anonymousKind, false)
+ if err := s.checkValue(elemID, elem); err != nil {
+ return err
+ }
+ }
}
+ default:
}
-
- // As inline tables are self-contained, the tracker does not
- // need to retain the details of what they contain. The
- // keyValue element that creates the inline table is kept to
- // mark the presence of the inline table and prevent
- // redefinition of its keys: check* functions cannot walk into
- // a value.
- pool.Put(s)
- return first, nil
+ return nil
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go
index bf031739..ed510382 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go
@@ -1 +1,2 @@
+// Package tracker provides functions for keeping track of AST nodes.
package tracker
diff --git a/vendor/github.com/pelletier/go-toml/v2/localtime.go b/vendor/github.com/pelletier/go-toml/v2/localtime.go
index a856bfdb..eb8c20e6 100644
--- a/vendor/github.com/pelletier/go-toml/v2/localtime.go
+++ b/vendor/github.com/pelletier/go-toml/v2/localtime.go
@@ -45,7 +45,7 @@ func (d *LocalDate) UnmarshalText(b []byte) error {
type LocalTime struct {
Hour int // Hour of the day: [0; 24[
Minute int // Minute of the hour: [0; 60[
- Second int // Second of the minute: [0; 60[
+ Second int // Second of the minute: [0; 59]
Nanosecond int // Nanoseconds within the second: [0, 1000000000[
Precision int // Number of digits to display for Nanosecond.
}
@@ -62,7 +62,7 @@ func (d LocalTime) String() string {
} else if d.Nanosecond > 0 {
// Nanoseconds are specified, but precision is not provided. Use the
// minimum.
- s += strings.Trim(fmt.Sprintf(".%09d", d.Nanosecond), "0")
+ s += strings.TrimRight(fmt.Sprintf(".%09d", d.Nanosecond), "0")
}
return s
@@ -77,7 +77,7 @@ func (d LocalTime) MarshalText() ([]byte, error) {
func (d *LocalTime) UnmarshalText(b []byte) error {
res, left, err := parseLocalTime(b)
if err == nil && len(left) != 0 {
- err = unstable.NewParserError(left, "extra characters")
+ err = unstable.NewParserError(left, "extra characters at the end of a local time")
}
if err != nil {
return err
@@ -111,12 +111,11 @@ func (d LocalDateTime) MarshalText() ([]byte, error) {
func (d *LocalDateTime) UnmarshalText(data []byte) error {
res, left, err := parseLocalDateTime(data)
if err == nil && len(left) != 0 {
- err = unstable.NewParserError(left, "extra characters")
+ err = unstable.NewParserError(left, "extra characters at the end of a local date time")
}
if err != nil {
return err
}
-
*d = res
return nil
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/marshaler.go b/vendor/github.com/pelletier/go-toml/v2/marshaler.go
index 161acd93..7f6a9408 100644
--- a/vendor/github.com/pelletier/go-toml/v2/marshaler.go
+++ b/vendor/github.com/pelletier/go-toml/v2/marshaler.go
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding"
"encoding/json"
+ "errors"
"fmt"
"io"
"math"
@@ -11,25 +12,37 @@ import (
"slices"
"strconv"
"strings"
+ "sync"
"time"
- "unicode"
+ "unicode/utf8"
- "github.com/pelletier/go-toml/v2/internal/characters"
+ "github.com/pelletier/go-toml/v2/internal/parserbridge"
+ "github.com/pelletier/go-toml/v2/unstable"
)
// Marshal serializes a Go value as a TOML document.
//
// It is a shortcut for Encoder.Encode() with the default options.
func Marshal(v interface{}) ([]byte, error) {
- var buf bytes.Buffer
- enc := NewEncoder(&buf)
+ enc := Encoder{indentSymbol: " "}
- err := enc.Encode(v)
+ e := encoderStatePool.Get().(*encoderState)
+ e.Encoder = &enc
+ e.marshalerOn = enc.marshalerInterface
+ e.buf = e.buf[:0]
+ e.keyStack = e.keyStack[:0]
+ e.lastWasHeader = false
+
+ err := e.encodeRoot(v)
if err != nil {
+ encoderStatePool.Put(e)
return nil, err
}
- return buf.Bytes(), nil
+ out := make([]byte, len(e.buf))
+ copy(out, e.buf)
+ encoderStatePool.Put(e)
+ return out, nil
}
// Encoder writes a TOML document to an output stream.
@@ -42,7 +55,10 @@ type Encoder struct {
arraysMultiline bool
indentSymbol string
indentTables bool
- marshalJsonNumbers bool
+ marshalJSONNumbers bool
+
+ // toggles the unstable.Marshaler interface
+ marshalerInterface bool
}
// NewEncoder returns a new Encoder that writes to w.
@@ -55,8 +71,8 @@ func NewEncoder(w io.Writer) *Encoder {
// SetTablesInline forces the encoder to emit all tables inline.
//
-// This behavior can be controlled on an individual struct field basis with the
-// inline tag:
+// This behavior can be controlled on an individual struct field basis with
+// the inline tag:
//
// MyField `toml:",inline"`
func (enc *Encoder) SetTablesInline(inline bool) *Encoder {
@@ -64,10 +80,11 @@ func (enc *Encoder) SetTablesInline(inline bool) *Encoder {
return enc
}
-// SetArraysMultiline forces the encoder to emit all arrays with one element per
-// line.
+// SetArraysMultiline forces the encoder to emit all arrays with one element
+// per line.
//
-// This behavior can be controlled on an individual struct field basis with the multiline tag:
+// This behavior can be controlled on an individual struct field basis with
+// the multiline tag:
//
// MyField `multiline:"true"`
func (enc *Encoder) SetArraysMultiline(multiline bool) *Encoder {
@@ -89,14 +106,43 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
return enc
}
-// SetMarshalJsonNumbers forces the encoder to serialize `json.Number` as a
+// SetMarshalJSONNumbers forces the encoder to serialize `json.Number` as a
// float or integer instead of relying on TextMarshaler to emit a string.
//
// *Unstable:* This method does not follow the compatibility guarantees of
// semver. It can be changed or removed without a new major version being
// issued.
-func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
- enc.marshalJsonNumbers = indent
+func (enc *Encoder) SetMarshalJSONNumbers(indent bool) *Encoder {
+ enc.marshalJSONNumbers = indent
+ return enc
+}
+
+// EnableMarshalerInterface enables the unstable.Marshaler interface.
+//
+// With this feature enabled, types implementing the unstable.Marshaler
+// interface emit their own raw TOML instead of being encoded structurally. It
+// is the encoding counterpart of Decoder.EnableUnmarshalerInterface, and allows
+// types such as unstable.RawMessage to round-trip raw TOML bytes.
+//
+// The bytes returned by MarshalTOML are spliced into the document verbatim. The
+// encoder parses them to decide between the valid positions:
+// - bytes forming a single value are emitted inline, as in `key = `;
+// - bytes forming key-value lines are emitted as the body of a `[key]` table;
+// - at the document root, the bytes are emitted as the whole document: the
+// encode counterpart of the decoder delivering the whole document to a
+// root unstable.Unmarshaler.
+//
+// An empty result is omitted from the output. Bytes that are not valid TOML
+// for their position result in an error, as do bytes forming table content in
+// a position where only a value is valid (an array element, an inline table,
+// or a table forced inline). MarshalTOML can be called more than once for the
+// same value during a single encode, so it must be deterministic.
+//
+// *Unstable:* This method does not follow the compatibility guarantees of
+// semver. It can be changed or removed without a new major version being
+// issued.
+func (enc *Encoder) EnableMarshalerInterface() *Encoder {
+ enc.marshalerInterface = true
return enc
}
@@ -118,9 +164,9 @@ func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
//
// Intermediate tables are always printed.
//
-// By default, strings are encoded as literal string, unless they contain either
-// a newline character or a single quote. In that case they are emitted as
-// quoted strings.
+// By default, strings are encoded as literal string, unless they contain
+// either a newline character or a single quote. In that case they are emitted
+// as quoted strings.
//
// Unsigned integers larger than math.MaxInt64 cannot be encoded. Doing so
// results in an error. This rule exists because the TOML specification only
@@ -129,8 +175,8 @@ func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
// readable (at best) by other implementations. To encode such numbers, a
// solution is a custom type that implements encoding.TextMarshaler.
//
-// When encoding structs, fields are encoded in order of definition, with their
-// exact name.
+// When encoding structs, fields are encoded in order of definition, with
+// their exact name.
//
// Tables and array tables are separated by empty lines. However, consecutive
// subtables definitions are not. For example:
@@ -150,984 +196,1502 @@ func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
// The encoding of each public struct field can be customized by the format
// string in the "toml" key of the struct field's tag. This follows
// encoding/json's convention. The format string starts with the name of the
-// field, optionally followed by a comma-separated list of options. The name may
-// be empty in order to provide options without overriding the default name.
+// field, optionally followed by a comma-separated list of options. The name
+// may be empty in order to provide options without overriding the default
+// name.
//
-// The "multiline" option emits strings as quoted multi-line TOML strings. It
-// has no effect on fields that would not be encoded as strings.
+// The "multiline" option emits strings as quoted multi-line TOML strings, and
+// arrays with one element per line. For strings, it only takes effect when the
+// value contains a newline; single-line values are emitted as regular strings.
+// It has no effect on fields that would not be encoded as strings or arrays.
//
-// The "inline" option turns fields that would be emitted as tables into inline
-// tables instead. It has no effect on other fields.
+// The "inline" option turns fields that would be emitted as tables into
+// inline tables instead. It has no effect on other fields.
//
// The "omitempty" option prevents empty values or groups from being emitted.
//
-// The "commented" option prefixes the value and all its children with a comment
-// symbol.
+// The "omitzero" option prevents zero values or groups from being emitted.
//
-// In addition to the "toml" tag struct tag, a "comment" tag can be used to emit
-// a TOML comment before the value being annotated. Comments are ignored inside
-// inline tables. For array tables, the comment is only present before the first
-// element of the array.
+// The "commented" option prefixes the value and all its children with a
+// comment symbol.
+//
+// In addition to the "toml" tag struct tag, a "comment" tag can be used to
+// emit a TOML comment before the value being annotated. Comments are ignored
+// inside inline tables. For array tables, the comment is only present before
+// the first element of the array.
func (enc *Encoder) Encode(v interface{}) error {
- var (
- b []byte
- ctx encoderCtx
- )
-
- ctx.inline = enc.tablesInline
-
- if v == nil {
- return fmt.Errorf("toml: cannot encode a nil interface")
- }
-
- b, err := enc.encode(b, ctx, reflect.ValueOf(v))
+ e := encoderStatePool.Get().(*encoderState)
+ e.Encoder = enc
+ e.marshalerOn = enc.marshalerInterface
+ e.buf = e.buf[:0]
+ e.keyStack = e.keyStack[:0]
+ e.lastWasHeader = false
+
+ err := e.encodeRoot(v)
if err != nil {
+ encoderStatePool.Put(e)
return err
}
- _, err = enc.w.Write(b)
+ _, err = enc.w.Write(e.buf)
+ encoderStatePool.Put(e)
if err != nil {
return fmt.Errorf("toml: cannot write: %w", err)
}
-
return nil
}
-type valueOptions struct {
- multiline bool
- omitempty bool
- commented bool
- comment string
+var encoderStatePool = sync.Pool{
+ New: func() interface{} { return &encoderState{} },
}
-type encoderCtx struct {
- // Current top-level key.
- parentKey []string
+type encoderState struct {
+ *Encoder
- // Key that should be used for a KV.
- key string
- // Extra flag to account for the empty string
- hasKey bool
+ buf []byte
- // Set to true to indicate that the encoder is inside a KV, so that all
- // tables need to be inlined.
- insideKv bool
+ // keyStack is the dotted key of the table being encoded, shared by the
+ // whole encode as a stack.
+ keyStack []string
- // Set to true to skip the first table header in an array table.
- skipTableHeader bool
+ // entriesPool recycles entry slices across tables of the same encode.
+ entriesPool [][]entry
- // Should the next table be encoded as inline
- inline bool
+ // lastWasHeader is true when the last line written was a table header,
+ // used to avoid empty lines between consecutive table definitions.
+ lastWasHeader bool
- // Indentation level
- indent int
+ // stringKeyBuf is a reusable buffer to read string map keys without
+ // allocating one per map.
+ stringKeyBuf reflect.Value
- // Prefix the current value with a comment.
- commented bool
+ // parser classifies the bytes returned by unstable.Marshaler values as a
+ // single value or a table body. Only used when marshalerOn is set.
+ parser unstable.Parser
- // Options coming from struct tags
- options valueOptions
+ // marshalerOn mirrors Encoder.marshalerInterface, copied onto the state so
+ // the per-value hot path checks a direct field instead of dereferencing the
+ // embedded *Encoder on every value.
+ marshalerOn bool
}
-func (ctx *encoderCtx) shiftKey() {
- if ctx.hasKey {
- ctx.parentKey = append(ctx.parentKey, ctx.key)
- ctx.clearKey()
- }
+// valueOptions are the encoding options attached to one entry of a table.
+type valueOptions struct {
+ multiline bool
+ inline bool
+ omitempty bool
+ omitzero bool
+ commented bool
+ // rawShape is the unstable.Marshaler classification of the entry's value,
+ // resolved at encode time (not from tags). It lives here, in the byte of
+ // padding the booleans already leave, so that entry does not grow and the
+ // encoder's default (interface-disabled) path keeps its exact layout and
+ // performance. It stays shapeUnknown for everything that is not a Marshaler.
+ rawShape rawShape
+ comment string
}
-func (ctx *encoderCtx) setKey(k string) {
- ctx.key = k
- ctx.hasKey = true
+// entry is a deferred key-value of a table being encoded.
+type entry struct {
+ key string
+ value reflect.Value
+ options valueOptions
}
-func (ctx *encoderCtx) clearKey() {
- ctx.key = ""
- ctx.hasKey = false
-}
+// rawShape classifies the bytes produced by an unstable.Marshaler.
+type rawShape uint8
+
+const (
+ // shapeUnknown is the default: not an unstable.Marshaler, or the interface
+ // is disabled.
+ shapeUnknown rawShape = iota
+ // shapeEmpty is whitespace-only content: it has no TOML representation and
+ // is omitted from the output.
+ shapeEmpty
+ // shapeValue is a single TOML value, emitted inline as `key = `.
+ shapeValue
+ // shapeTable is one or more key-value lines, emitted as a `[key]` body.
+ shapeTable
+)
-func (ctx *encoderCtx) isRoot() bool {
- return len(ctx.parentKey) == 0 && !ctx.hasKey
-}
+func (e *encoderState) encodeRoot(v interface{}) error {
+ if v == nil {
+ return errors.New("toml: cannot encode a nil interface")
+ }
-func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
- i := v.Interface()
+ rv := reflect.ValueOf(v)
+ rv, ok := resolve(rv)
+ if !ok {
+ return errors.New("toml: cannot encode a nil pointer")
+ }
- switch x := i.(type) {
- case time.Time:
- if x.Nanosecond() > 0 {
- return x.AppendFormat(b, time.RFC3339Nano), nil
- }
- return x.AppendFormat(b, time.RFC3339), nil
- case LocalTime:
- return append(b, x.String()...), nil
- case LocalDate:
- return append(b, x.String()...), nil
- case LocalDateTime:
- return append(b, x.String()...), nil
- case json.Number:
- if enc.marshalJsonNumbers {
- if x == "" { /// Useful zero value.
- return append(b, "0"...), nil
- } else if v, err := x.Int64(); err == nil {
- return enc.encode(b, ctx, reflect.ValueOf(v))
- } else if f, err := x.Float64(); err == nil {
- return enc.encode(b, ctx, reflect.ValueOf(f))
- } else {
- return nil, fmt.Errorf("toml: unable to convert %q to int64 or float64", x)
- }
- }
+ if e.marshalerOn && encPropsForType(rv.Type()).marshaler != 0 {
+ return e.encodeMarshalerRoot(rv)
}
- hasTextMarshaler := v.Type().Implements(textMarshalerType)
- if hasTextMarshaler || (v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) {
- if !hasTextMarshaler {
- v = v.Addr()
+ switch rv.Kind() {
+ case reflect.Map, reflect.Struct:
+ if isValueKind(rv) {
+ return fmt.Errorf("toml: cannot encode a %s as a document root", rv.Type())
}
+ return e.encodeTable(rv, false, 0)
+ default:
+ return fmt.Errorf("toml: cannot encode a %s as a document root", rv.Type())
+ }
+}
- if ctx.isRoot() {
- return nil, fmt.Errorf("toml: type %s implementing the TextMarshaler interface cannot be a root element", v.Type())
+// encodeMarshalerRoot emits the bytes of a root-level unstable.Marshaler as
+// the whole document: the encode counterpart of the decoder delivering the
+// whole document to a root Unmarshaler. The bytes must form a TOML document
+// (key-value lines and table headers); empty output produces an empty
+// document.
+func (e *encoderState) encodeMarshalerRoot(rv reflect.Value) error {
+ raw, err := e.marshalerBytes(rv)
+ if err != nil {
+ return err
+ }
+ trimmed := bytes.TrimSpace(raw)
+ if len(trimmed) == 0 {
+ return nil
+ }
+ if err := e.validateRawTableBody(rv.Type(), trimmed); err != nil {
+ // A single TOML value has no meaning at the document root; report it
+ // as such rather than as a syntax error.
+ if shape, _ := e.classifyRaw(trimmed); shape == shapeValue {
+ return fmt.Errorf("toml: cannot encode %s as a document root: MarshalTOML returned a single TOML value, not a document", rv.Type())
}
+ return err
+ }
+ e.buf = append(e.buf, trimmed...)
+ e.buf = append(e.buf, '\n')
+ e.lastWasHeader = false
+ return nil
+}
- text, err := v.Interface().(encoding.TextMarshaler).MarshalText()
- if err != nil {
- return nil, err
+// resolve unwraps pointers and interfaces until a concrete value is found.
+// Returns false if it resolves to nil.
+func resolve(v reflect.Value) (reflect.Value, bool) {
+ for {
+ switch v.Kind() {
+ case reflect.Ptr:
+ if v.IsNil() {
+ return v, false
+ }
+ v = v.Elem()
+ case reflect.Interface:
+ if v.IsNil() {
+ return v, false
+ }
+ v = v.Elem()
+ default:
+ return v, true
}
+ }
+}
- b = enc.encodeString(b, string(text), ctx.options)
+// typeEncProps caches the per-type facts used on every value encode.
+type typeEncProps struct {
+ // 0: not a TextMarshaler, 1: the type implements it, 2: its pointer does
+ text uint8
+ // 0: not an unstable.Marshaler, 1: the type implements it, 2: its pointer
+ // does. Only consulted when Encoder.marshalerInterface is set.
+ marshaler uint8
+ // encoded as a TOML value (as opposed to a table)
+ isValue bool
+}
- return b, nil
- }
+var marshalerType = reflect.TypeOf(new(unstable.Marshaler)).Elem()
- switch v.Kind() {
- // containers
- case reflect.Map:
- return enc.encodeMap(b, ctx, v)
- case reflect.Struct:
- return enc.encodeStruct(b, ctx, v)
- case reflect.Slice, reflect.Array:
- return enc.encodeSlice(b, ctx, v)
- case reflect.Interface:
- if v.IsNil() {
- return nil, fmt.Errorf("toml: encoding a nil interface is not supported")
- }
+var typeEncPropsCache sync.Map // reflect.Type -> typeEncProps
- return enc.encode(b, ctx, v.Elem())
- case reflect.Ptr:
- if v.IsNil() {
- return enc.encode(b, ctx, reflect.Zero(v.Type().Elem()))
+func encPropsForType(t reflect.Type) typeEncProps {
+ if p, ok := typeEncPropsCache.Load(t); ok {
+ return p.(typeEncProps)
+ }
+ var p typeEncProps
+ switch {
+ case t.Implements(textMarshalerType):
+ p.text = 1
+ case reflect.PtrTo(t).Implements(textMarshalerType):
+ p.text = 2
+ }
+ switch {
+ case t.Implements(marshalerType):
+ p.marshaler = 1
+ case reflect.PtrTo(t).Implements(marshalerType):
+ p.marshaler = 2
+ }
+ switch t {
+ case timeType, localDateType, localTimeType, localDateTimeType:
+ p.isValue = true
+ default:
+ if p.text != 0 {
+ p.isValue = true
+ } else {
+ switch t.Kind() {
+ case reflect.Map, reflect.Struct:
+ p.isValue = false
+ default:
+ p.isValue = true
+ }
}
+ }
+ typeEncPropsCache.Store(t, p)
+ return p
+}
- return enc.encode(b, ctx, v.Elem())
+// isValueKind returns true when the resolved value is encoded as a TOML
+// value (as opposed to a table).
+func isValueKind(v reflect.Value) bool {
+ return encPropsForType(v.Type()).isValue
+}
- // values
- case reflect.String:
- b = enc.encodeString(b, v.String(), ctx.options)
- case reflect.Float32:
- f := v.Float()
-
- if math.IsNaN(f) {
- b = append(b, "nan"...)
- } else if f > math.MaxFloat32 {
- b = append(b, "inf"...)
- } else if f < -math.MaxFloat32 {
- b = append(b, "-inf"...)
- } else if math.Trunc(f) == f {
- b = strconv.AppendFloat(b, f, 'f', 1, 32)
- } else {
- b = strconv.AppendFloat(b, f, 'f', -1, 32)
+// isTableLike returns true when the value should be encoded as a table (or
+// an array of tables for slices).
+func (e *encoderState) isTableLike(v reflect.Value) bool {
+ v, ok := resolve(v)
+ if !ok {
+ // Unresolvable values (interface-held nil pointers) are encoded as
+ // the zero value of their element type by the value path.
+ return false
+ }
+ return !isValueKind(v)
+}
+
+// isArrayOfTables returns true when the value is a non-empty slice or array
+// containing only table-like values.
+func (e *encoderState) isArrayOfTables(v reflect.Value) bool {
+ v, ok := resolve(v)
+ if !ok {
+ return false
+ }
+ if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
+ return false
+ }
+ if v.Len() == 0 {
+ return false
+ }
+ // The Marshaler-aware classification lives in a separate method, hoisted out
+ // of this loop, so the default path keeps its exact original shape.
+ if e.marshalerOn {
+ return e.isMarshalerArrayOfTables(v)
+ }
+ for i := 0; i < v.Len(); i++ {
+ elem, ok := resolve(v.Index(i))
+ if !ok || isValueKind(elem) {
+ return false
}
- case reflect.Float64:
- f := v.Float()
- if math.IsNaN(f) {
- b = append(b, "nan"...)
- } else if f > math.MaxFloat64 {
- b = append(b, "inf"...)
- } else if f < -math.MaxFloat64 {
- b = append(b, "-inf"...)
- } else if math.Trunc(f) == f {
- b = strconv.AppendFloat(b, f, 'f', 1, 64)
- } else {
- b = strconv.AppendFloat(b, f, 'f', -1, 64)
+ }
+ return true
+}
+
+// isMarshalerArrayOfTables is the EnableMarshalerInterface variant of
+// isArrayOfTables: a Marshaler element counts as a table only when its raw
+// content is table shaped (key-value lines); one holding a single value makes
+// the whole slice a plain array instead.
+func (e *encoderState) isMarshalerArrayOfTables(v reflect.Value) bool {
+ for i := 0; i < v.Len(); i++ {
+ elem, ok := resolve(v.Index(i))
+ if !ok {
+ return false
}
- case reflect.Bool:
- if v.Bool() {
- b = append(b, "true"...)
- } else {
- b = append(b, "false"...)
+ if encPropsForType(elem.Type()).marshaler != 0 {
+ raw, err := e.marshalerBytes(elem)
+ if err != nil {
+ return false
+ }
+ if shape, _ := e.classifyRaw(raw); shape != shapeTable {
+ return false
+ }
+ continue
}
- case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint:
- x := v.Uint()
- if x > uint64(math.MaxInt64) {
- return nil, fmt.Errorf("toml: not encoding uint (%d) greater than max int64 (%d)", x, int64(math.MaxInt64))
+ if isValueKind(elem) {
+ return false
}
- b = strconv.AppendUint(b, x, 10)
- case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
- b = strconv.AppendInt(b, v.Int(), 10)
- default:
- return nil, fmt.Errorf("toml: cannot encode value of type %s", v.Kind())
}
-
- return b, nil
+ return true
}
-func isNil(v reflect.Value) bool {
- switch v.Kind() {
- case reflect.Ptr, reflect.Interface, reflect.Map:
- return v.IsNil()
+// marshalerBytes returns the raw TOML produced by v's unstable.Marshaler
+// implementation. The caller guarantees v implements the interface
+// (encPropsForType(v.Type()).marshaler != 0).
+func (e *encoderState) marshalerBytes(v reflect.Value) ([]byte, error) {
+ t := v.Type()
+ var m unstable.Marshaler
+ switch {
+ case encPropsForType(t).marshaler == 1:
+ // The type itself implements Marshaler (e.g. a value receiver).
+ m = v.Interface().(unstable.Marshaler)
+ case v.CanAddr():
+ // Only the pointer implements it, and v is addressable.
+ m = v.Addr().Interface().(unstable.Marshaler)
default:
- return false
+ // Only the pointer implements it, but v is not addressable: take the
+ // address of a copy.
+ tmp := reflect.New(t)
+ tmp.Elem().Set(v)
+ m = tmp.Interface().(unstable.Marshaler)
}
+ b, err := m.MarshalTOML()
+ if err != nil {
+ return nil, fmt.Errorf("toml: error calling MarshalTOML for type %s: %w", t, err)
+ }
+ return b, nil
}
-func shouldOmitEmpty(options valueOptions, v reflect.Value) bool {
- return options.omitempty && isEmptyValue(v)
+// validateRawTableBody checks that trimmed — table-shaped Marshaler output
+// about to be spliced verbatim — is syntactically valid TOML, so a Marshaler
+// cannot silently corrupt the document. It reuses e.parser, like classifyRaw.
+func (e *encoderState) validateRawTableBody(t reflect.Type, trimmed []byte) error {
+ e.parser.Reset(trimmed)
+ for e.parser.NextExpression() {
+ }
+ if err := e.parser.Error(); err != nil {
+ return fmt.Errorf("toml: error calling MarshalTOML for type %s: invalid TOML: %w", t, err)
+ }
+ return nil
}
-func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v reflect.Value) ([]byte, error) {
- var err error
-
- if !ctx.inline {
- b = enc.encodeComment(ctx.indent, options.comment, b)
- b = enc.commented(ctx.commented, b)
- b = enc.indent(ctx.indent, b)
+// classifyRaw decides whether b (the output of an unstable.Marshaler) is empty,
+// a single TOML value, or a table body. It returns the trimmed bytes that
+// should be spliced into the document. It reuses e.parser, so it is not safe
+// for concurrent use (encoderState is not shared).
+func (e *encoderState) classifyRaw(b []byte) (rawShape, []byte) {
+ trimmed := bytes.TrimSpace(b)
+ if len(trimmed) == 0 {
+ return shapeEmpty, trimmed
}
+ e.parser.Reset(trimmed)
+ _, rest, err := parserbridge.ParseValue(&e.parser, trimmed)
+ if err == nil && len(bytes.TrimSpace(rest)) == 0 {
+ return shapeValue, trimmed
+ }
+ return shapeTable, trimmed
+}
- b = enc.encodeKey(b, ctx.key)
- b = append(b, " = "...)
-
- // create a copy of the context because the value of a KV shouldn't
- // modify the global context.
- subctx := ctx
- subctx.insideKv = true
- subctx.shiftKey()
- subctx.options = options
+// resolveMarshalerEntries classifies every entry whose value implements
+// unstable.Marshaler, recording the shape on the entry so the two table passes
+// can route it without re-classifying. Any error from MarshalTOML is surfaced
+// eagerly. The marshaled bytes themselves are produced again at emit time by
+// marshalerValue; that keeps entry small on the encoder's hot path, and only
+// runs when the (opt-in) interface is enabled.
+func (e *encoderState) resolveMarshalerEntries(entries []entry) error {
+ for i := range entries {
+ ent := &entries[i]
+ v, ok := resolve(ent.value)
+ if !ok || encPropsForType(v.Type()).marshaler == 0 {
+ continue
+ }
+ raw, err := e.marshalerBytes(v)
+ if err != nil {
+ return err
+ }
+ ent.options.rawShape, _ = e.classifyRaw(raw)
+ }
+ return nil
+}
- b, err = enc.encode(b, subctx, v)
+// marshalerValue returns the trimmed bytes to splice for an entry already known
+// to be an unstable.Marshaler (ent.options.rawShape != shapeUnknown).
+func (e *encoderState) marshalerValue(ent *entry) ([]byte, error) {
+ v, _ := resolve(ent.value)
+ raw, err := e.marshalerBytes(v)
if err != nil {
return nil, err
}
-
- return b, nil
+ return bytes.TrimSpace(raw), nil
}
-func (enc *Encoder) commented(commented bool, b []byte) []byte {
- if commented {
- return append(b, "# "...)
+// appendMarshalerInline emits an unstable.Marshaler value in a value position
+// (array element or inline-table member), where only a single TOML value is
+// valid. done is false when t is not a Marshaler, so appendValue falls through
+// to its normal handling. It is split out of appendValue (type check included)
+// to keep that hot path lean.
+func (e *encoderState) appendMarshalerInline(b []byte, v reflect.Value, t reflect.Type) (out []byte, done bool, err error) {
+ if encPropsForType(t).marshaler == 0 {
+ return b, false, nil
+ }
+ raw, err := e.marshalerBytes(v)
+ if err != nil {
+ return nil, true, err
+ }
+ shape, trimmed := e.classifyRaw(raw)
+ switch shape {
+ case shapeValue:
+ return append(b, trimmed...), true, nil
+ case shapeEmpty:
+ return nil, true, fmt.Errorf("toml: cannot encode an empty %s as an inline value", t)
+ default:
+ return nil, true, fmt.Errorf("toml: cannot encode %s as an inline value: %q is not a single TOML value", t, trimmed)
}
- return b
}
-func isEmptyValue(v reflect.Value) bool {
- switch v.Kind() {
- case reflect.Struct:
- return isEmptyStruct(v)
- case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
- return v.Len() == 0
- case reflect.Bool:
- return !v.Bool()
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return v.Int() == 0
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- return v.Uint() == 0
- case reflect.Float32, reflect.Float64:
- return v.Float() == 0
- case reflect.Interface, reflect.Ptr:
- return v.IsNil()
+// encodeTable writes the content of a table at the given key path.
+func (e *encoderState) encodeTable(v reflect.Value, commented bool, indent int) error {
+ entries, err := e.collectEntries(v)
+ if err != nil {
+ return err
}
- return false
-}
-func isEmptyStruct(v reflect.Value) bool {
- // TODO: merge with walkStruct and cache.
- typ := v.Type()
- for i := 0; i < typ.NumField(); i++ {
- fieldType := typ.Field(i)
+ // Marshaler routing is hoisted behind a single local flag. When the (opt-in)
+ // interface is off, mOn is false and both passes run the exact baseline
+ // code, so the default Marshal path keeps its performance.
+ mOn := e.marshalerOn
+ if mOn {
+ // Classify Marshaler entries once, up front, so the passes can route
+ // them by shape and surface MarshalTOML errors eagerly.
+ if err := e.resolveMarshalerEntries(entries); err != nil {
+ return err
+ }
+ }
- // only consider exported fields
- if fieldType.PkgPath != "" {
+ // First pass: emit all key-values; tables are handled by the second
+ // pass.
+ for i := range entries {
+ ent := &entries[i]
+ if mOn {
+ switch ent.options.rawShape {
+ case shapeUnknown:
+ // Not a Marshaler: handled by the baseline logic below.
+ case shapeEmpty:
+ // No TOML representation: omit the key.
+ continue
+ case shapeValue:
+ if err := e.encodeKeyValue(*ent, commented, indent); err != nil {
+ return err
+ }
+ continue
+ case shapeTable:
+ // A table body is emitted in the second pass, unless it is
+ // forced inline (SetTablesInline / inline tag), which has no
+ // valid inline form and is reported as an error by
+ // encodeKeyValue.
+ if e.tablesInline || ent.options.inline {
+ if err := e.encodeKeyValue(*ent, commented, indent); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ }
+ if e.entryIsTable(ent) {
continue
}
+ if err := e.encodeKeyValue(*ent, commented, indent); err != nil {
+ return err
+ }
+ }
- tag := fieldType.Tag.Get("toml")
+ // Second pass: emit the sub-tables, extending the shared key stack.
+ for i := range entries {
+ ent := entries[i]
+ if mOn {
+ switch ent.options.rawShape {
+ case shapeUnknown:
+ // Not a Marshaler: handled by the baseline logic below.
+ case shapeValue, shapeEmpty:
+ // Not a table: already handled (or omitted) in the first pass.
+ continue
+ case shapeTable:
+ // Emit the raw body verbatim under the freshly pushed header.
+ // (The forced-inline case already errored in the first pass.)
+ entCommented := commented || ent.options.commented
+ e.keyStack = append(e.keyStack, ent.key)
+ if err := e.encodeMarshalerTable(&ent, entCommented, indent); err != nil {
+ return err
+ }
+ e.keyStack = e.keyStack[:len(e.keyStack)-1]
+ continue
+ }
+ }
+ if !e.entryIsTable(&ent) {
+ continue
+ }
+ entCommented := commented || ent.options.commented
+ e.keyStack = append(e.keyStack, ent.key)
- // special field name to skip field
- if tag == "-" {
+ if e.isArrayOfTables(ent.value) {
+ err := e.encodeArrayTable(ent, entCommented, indent)
+ if err != nil {
+ return err
+ }
+ e.keyStack = e.keyStack[:len(e.keyStack)-1]
continue
}
- f := v.Field(i)
+ // The value is resolvable: entryIsTable already resolved it.
+ tv, _ := resolve(ent.value)
- if !isEmptyValue(f) {
- return false
+ e.writeTableHeader(ent.options.comment, entCommented, false, indent)
+
+ err := e.encodeTable(tv, entCommented, indent+1)
+ if err != nil {
+ return err
}
+ e.keyStack = e.keyStack[:len(e.keyStack)-1]
}
- return true
+ e.putEntries(entries)
+ return nil
}
-const literalQuote = '\''
-
-func (enc *Encoder) encodeString(b []byte, v string, options valueOptions) []byte {
- if needsQuoting(v) {
- return enc.encodeQuotedString(options.multiline, b, v)
+// encodeMarshalerTable emits a table-shaped unstable.Marshaler entry: the
+// header for the key currently on the stack, then the raw body verbatim.
+func (e *encoderState) encodeMarshalerTable(ent *entry, commented bool, indent int) error {
+ raw, err := e.marshalerValue(ent)
+ if err != nil {
+ return err
}
-
- return enc.encodeLiteralString(b, v)
+ // Validate the bytes actually being spliced: MarshalTOML is called again
+ // for the emit, so this both rejects invalid TOML and guards against an
+ // implementation that returned different content than during
+ // classification.
+ if err := e.validateRawTableBody(ent.value.Type(), raw); err != nil {
+ return err
+ }
+ e.writeTableHeader(ent.options.comment, commented, false, indent)
+ e.spliceRawTableBody(raw, commented)
+ return nil
}
-func needsQuoting(v string) bool {
- // TODO: vectorize
- for _, b := range []byte(v) {
- if b == '\'' || b == '\r' || b == '\n' || characters.InvalidAscii(b) {
- return true
- }
+// spliceRawTableBody appends a raw table body verbatim after its header. When
+// the table is commented, every physical line is prefixed with the comment
+// marker so the body does not leak into the document as live keys.
+func (e *encoderState) spliceRawTableBody(raw []byte, commented bool) {
+ if len(raw) == 0 {
+ return
+ }
+ if commented {
+ e.buf = append(e.buf, "# "...)
+ e.buf = append(e.buf, bytes.ReplaceAll(raw, []byte("\n"), []byte("\n# "))...)
+ } else {
+ e.buf = append(e.buf, raw...)
}
- return false
+ e.buf = append(e.buf, '\n')
+ e.lastWasHeader = false
}
-// caller should have checked that the string does not contain new lines or ' .
-func (enc *Encoder) encodeLiteralString(b []byte, v string) []byte {
- b = append(b, literalQuote)
- b = append(b, v...)
- b = append(b, literalQuote)
-
- return b
+// entryIsTable reports whether the entry is emitted as a (sub-)table rather
+// than a key-value. Marshaler entries are routed by encodeTable before this is
+// reached, so it carries no marshaler-specific cost.
+func (e *encoderState) entryIsTable(ent *entry) bool {
+ return !e.tablesInline && !ent.options.inline && (e.isTableLike(ent.value) || e.isArrayOfTables(ent.value))
}
-func (enc *Encoder) encodeQuotedString(multiline bool, b []byte, v string) []byte {
- stringQuote := `"`
-
- if multiline {
- stringQuote = `"""`
+// getEntries returns a reusable entry slice.
+func (e *encoderState) getEntries() []entry {
+ if n := len(e.entriesPool); n > 0 {
+ s := e.entriesPool[n-1]
+ e.entriesPool = e.entriesPool[:n-1]
+ return s[:0]
}
+ return nil
+}
- b = append(b, stringQuote...)
- if multiline {
- b = append(b, '\n')
+// putEntries returns an entry slice to the pool.
+func (e *encoderState) putEntries(s []entry) {
+ if cap(s) > 0 {
+ e.entriesPool = append(e.entriesPool, s)
}
+}
- const (
- hextable = "0123456789ABCDEF"
- // U+0000 to U+0008, U+000A to U+001F, U+007F
- nul = 0x0
- bs = 0x8
- lf = 0xa
- us = 0x1f
- del = 0x7f
- )
-
- for _, r := range []byte(v) {
- switch r {
- case '\\':
- b = append(b, `\\`...)
- case '"':
- b = append(b, `\"`...)
- case '\b':
- b = append(b, `\b`...)
- case '\f':
- b = append(b, `\f`...)
- case '\n':
- if multiline {
- b = append(b, r)
- } else {
- b = append(b, `\n`...)
+// encodeArrayTable writes all the elements of an array of tables.
+func (e *encoderState) encodeArrayTable(ent entry, commented bool, indent int) error {
+ v, _ := resolve(ent.value)
+ comment := ent.options.comment
+ for i := 0; i < v.Len(); i++ {
+ // Elements are resolvable: isArrayOfTables already resolved them.
+ elem, _ := resolve(v.Index(i))
+
+ e.writeTableHeader(comment, commented, true, indent)
+ // The comment is only present before the first element.
+ comment = ""
+
+ // A Marshaler element splices its raw table body verbatim. The shape
+ // was checked by isArrayOfTables, but MarshalTOML is called again for
+ // the emit, so the spliced bytes are validated here.
+ if e.marshalerOn && encPropsForType(elem.Type()).marshaler != 0 {
+ raw, err := e.marshalerBytes(elem)
+ if err != nil {
+ return err
}
- case '\r':
- b = append(b, `\r`...)
- case '\t':
- b = append(b, `\t`...)
- default:
- switch {
- case r >= nul && r <= bs, r >= lf && r <= us, r == del:
- b = append(b, `\u00`...)
- b = append(b, hextable[r>>4])
- b = append(b, hextable[r&0x0f])
- default:
- b = append(b, r)
+ trimmed := bytes.TrimSpace(raw)
+ if err := e.validateRawTableBody(elem.Type(), trimmed); err != nil {
+ return err
}
+ e.spliceRawTableBody(trimmed, commented)
+ continue
}
- }
-
- b = append(b, stringQuote...)
-
- return b
-}
-// caller should have checked that the string is in A-Z / a-z / 0-9 / - / _ .
-func (enc *Encoder) encodeUnquotedKey(b []byte, v string) []byte {
- return append(b, v...)
+ err := e.encodeTable(elem, commented, indent+1)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
}
-func (enc *Encoder) encodeTableHeader(ctx encoderCtx, b []byte) ([]byte, error) {
- if len(ctx.parentKey) == 0 {
- return b, nil
+// writeTableHeader emits a [table] or [[array table]] header line, preceded
+// by an empty line and comments as needed.
+func (e *encoderState) writeTableHeader(comment string, commented bool, array bool, indent int) {
+ key := e.keyStack
+ if len(e.buf) > 0 && !e.lastWasHeader {
+ e.buf = append(e.buf, '\n')
}
- b = enc.encodeComment(ctx.indent, ctx.options.comment, b)
-
- b = enc.commented(ctx.commented, b)
-
- b = enc.indent(ctx.indent, b)
-
- b = append(b, '[')
+ headerIndent := indent
- b = enc.encodeKey(b, ctx.parentKey[0])
+ e.writeComment(comment, headerIndent)
- for _, k := range ctx.parentKey[1:] {
- b = append(b, '.')
- b = enc.encodeKey(b, k)
+ // The "commented" marker is emitted at column zero, ahead of any table
+ // indentation, so that the indentation appears inside the comment
+ // (e.g. `# [a.b]`). This matches the historical v2.3 layout.
+ if commented {
+ e.buf = append(e.buf, "# "...)
}
-
- b = append(b, "]\n"...)
-
- return b, nil
-}
-
-//nolint:cyclop
-func (enc *Encoder) encodeKey(b []byte, k string) []byte {
- needsQuotation := false
- cannotUseLiteral := false
-
- if len(k) == 0 {
- return append(b, "''"...)
+ e.writeIndent(headerIndent)
+ e.buf = append(e.buf, '[')
+ if array {
+ e.buf = append(e.buf, '[')
}
-
- for _, c := range k {
- if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' {
- continue
- }
-
- if c == literalQuote {
- cannotUseLiteral = true
+ for i, part := range key {
+ if i > 0 {
+ e.buf = append(e.buf, '.')
}
-
- needsQuotation = true
+ e.buf = e.appendKey(e.buf, part)
}
-
- if needsQuotation && needsQuoting(k) {
- cannotUseLiteral = true
+ e.buf = append(e.buf, ']')
+ if array {
+ e.buf = append(e.buf, ']')
}
+ e.buf = append(e.buf, '\n')
+ e.lastWasHeader = true
+}
- switch {
- case cannotUseLiteral:
- return enc.encodeQuotedString(false, b, k)
- case needsQuotation:
- return enc.encodeLiteralString(b, k)
- default:
- return enc.encodeUnquotedKey(b, k)
+func (e *encoderState) writeIndent(indent int) {
+ if !e.indentTables {
+ return
+ }
+ for i := 0; i < indent; i++ {
+ e.buf = append(e.buf, e.indentSymbol...)
}
}
-func (enc *Encoder) keyToString(k reflect.Value) (string, error) {
- keyType := k.Type()
- switch {
- case keyType.Kind() == reflect.String:
- return k.String(), nil
+// writeComment emits the comment lines attached to an entry.
+func (e *encoderState) writeComment(comment string, indent int) {
+ if comment == "" {
+ return
+ }
+ for _, line := range strings.Split(comment, "\n") {
+ e.writeIndent(indent)
+ e.buf = append(e.buf, "# "...)
+ e.buf = append(e.buf, line...)
+ e.buf = append(e.buf, '\n')
+ }
+}
- case keyType.Implements(textMarshalerType):
- keyB, err := k.Interface().(encoding.TextMarshaler).MarshalText()
- if err != nil {
- return "", fmt.Errorf("toml: error marshalling key %v from text: %w", k, err)
- }
- return string(keyB), nil
+// encodeKeyValue writes one `key = value` line of a table.
+func (e *encoderState) encodeKeyValue(ent entry, commented bool, indent int) error {
+ commented = commented || ent.options.commented
- case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64:
- return strconv.FormatInt(k.Int(), 10), nil
+ e.writeComment(ent.options.comment, indent)
- case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64:
- return strconv.FormatUint(k.Uint(), 10), nil
+ // The "commented" marker is emitted at column zero, ahead of any table
+ // indentation, so that the indentation appears inside the comment
+ // (e.g. `# key = value`). This matches the historical v2.3 layout.
+ lineStart := len(e.buf)
+ if commented {
+ e.buf = append(e.buf, "# "...)
+ }
+ e.writeIndent(indent)
+ e.buf = e.appendKey(e.buf, ent.key)
+ e.buf = append(e.buf, " = "...)
+
+ // When tables are not indented, the key is emitted at column zero
+ // regardless of its nesting depth. Value continuation lines (most
+ // notably the elements of a multiline array) must line up with that key,
+ // so the value indentation starts from zero as well rather than from the
+ // table nesting depth.
+ valueIndent := indent
+ if !e.indentTables {
+ valueIndent = 0
+ }
- case keyType.Kind() == reflect.Float32:
- return strconv.FormatFloat(k.Float(), 'f', -1, 32), nil
+ // A Marshaler value is delegated, keeping this hot function lean for the
+ // default path (rawShape stays shapeUnknown when the interface is off). It
+ // shares the commented/newline handling below.
+ var err error
+ if ent.options.rawShape != shapeUnknown {
+ e.buf, err = e.appendMarshalerInlineValue(e.buf, &ent)
+ } else {
+ e.buf, err = e.appendValue(e.buf, ent.value, ent.options, valueIndent)
+ }
+ if err != nil {
+ return err
+ }
- case keyType.Kind() == reflect.Float64:
- return strconv.FormatFloat(k.Float(), 'f', -1, 64), nil
+ // A commented value that renders across multiple lines (a multiline string
+ // or a multiline array) must have every physical line prefixed with the
+ // comment marker, not just the first; otherwise the continuation lines are
+ // emitted as live, syntactically invalid TOML.
+ if commented {
+ if bytes.IndexByte(e.buf[lineStart:], '\n') >= 0 {
+ region := bytes.ReplaceAll(
+ append([]byte(nil), e.buf[lineStart:]...),
+ []byte("\n"), []byte("\n# "),
+ )
+ e.buf = append(e.buf[:lineStart], region...)
+ }
}
- return "", fmt.Errorf("toml: type %s is not supported as a map key", keyType.Kind())
+ e.buf = append(e.buf, '\n')
+ e.lastWasHeader = false
+ return nil
}
-func (enc *Encoder) encodeMap(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
- var (
- t table
- emptyValueOptions valueOptions
- )
+// appendMarshalerInlineValue appends the value part of a `key = ` line for an
+// unstable.Marshaler entry, leaving the trailing newline and commented handling
+// to encodeKeyValue. Empty entries are filtered out before this point, so the
+// value is either a single value (spliced verbatim) or, when forced inline by
+// SetTablesInline or an inline tag, table content (an error).
+func (e *encoderState) appendMarshalerInlineValue(b []byte, ent *entry) ([]byte, error) {
+ errNotValue := func() error {
+ return fmt.Errorf("toml: cannot encode %s as an inline value: not a single TOML value", ent.value.Type())
+ }
+ if ent.options.rawShape != shapeValue {
+ return nil, errNotValue()
+ }
+ raw, err := e.marshalerValue(ent)
+ if err != nil {
+ return nil, err
+ }
+ // Classify the just-returned bytes rather than trusting the earlier pass:
+ // MarshalTOML is called again for the emit, and an implementation that
+ // returns different content must not splice non-value bytes into a
+ // `key = ` position.
+ if shape, trimmed := e.classifyRaw(raw); shape == shapeValue {
+ return append(b, trimmed...), nil
+ }
+ return nil, errNotValue()
+}
- iter := v.MapRange()
- for iter.Next() {
- v := iter.Value()
+// collectEntries builds the ordered list of the entries of a table,
+// applying tags and omission rules.
+func (e *encoderState) collectEntries(v reflect.Value) ([]entry, error) {
+ switch v.Kind() {
+ case reflect.Map:
+ return e.collectMapEntries(v)
+ case reflect.Struct:
+ entries := e.getEntries()
+ e.collectStructEntries(&entries, v)
+ return entries, nil
+ default:
+ return nil, fmt.Errorf("toml: cannot encode a %s as a table", v.Type())
+ }
+}
- if isNil(v) {
- continue
+func (e *encoderState) collectMapEntries(v reflect.Value) ([]entry, error) {
+ entries := e.getEntries()
+
+ // Keys are converted to strings right away: read them into a reusable
+ // buffer to avoid one allocation per key.
+ var kbuf reflect.Value
+ if v.Type().Key() == stringType {
+ if !e.stringKeyBuf.IsValid() {
+ e.stringKeyBuf = reflect.New(stringType).Elem()
}
+ kbuf = e.stringKeyBuf
+ } else {
+ kbuf = reflect.New(v.Type().Key()).Elem()
+ }
- k, err := enc.keyToString(iter.Key())
+ iter := v.MapRange()
+ for iter.Next() {
+ kbuf.SetIterKey(iter)
+ key, err := mapKeyString(kbuf)
if err != nil {
return nil, err
}
-
- if willConvertToTableOrArrayTable(ctx, v) {
- t.pushTable(k, v, emptyValueOptions)
- } else {
- t.pushKV(k, v, emptyValueOptions)
+ value := iter.Value()
+ if value.Kind() == reflect.Interface && value.IsNil() {
+ // nil interface values are skipped
+ continue
+ }
+ if value.Kind() == reflect.Ptr && value.IsNil() {
+ // nil pointers in maps are encoded as their zero value
+ value = reflect.New(value.Type().Elem()).Elem()
}
+ entries = append(entries, entry{key: key, value: value})
}
- sortEntriesByKey(t.kvs)
- sortEntriesByKey(t.tables)
+ if len(entries) > 1 {
+ // slices.SortFunc avoids boxing the slice into a sort.Interface (an
+ // allocation that sort.Sort incurs for every table).
+ slices.SortFunc(entries, func(a, b entry) int {
+ return strings.Compare(a.key, b.key)
+ })
+ }
- return enc.encodeTable(b, ctx, t)
+ return entries, nil
}
-func sortEntriesByKey(e []entry) {
- slices.SortFunc(e, func(a, b entry) int {
- return strings.Compare(a.Key, b.Key)
- })
+// mapKeyString converts a map key to its string representation.
+func mapKeyString(k reflect.Value) (string, error) {
+ kr, ok := resolve(k)
+ if !ok {
+ return "", errors.New("toml: cannot encode a nil map key")
+ }
+ if kr.Type().Implements(textMarshalerType) {
+ b, err := kr.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return "", fmt.Errorf("toml: cannot marshal map key: %w", err)
+ }
+ return string(b), nil
+ }
+ if kr.CanAddr() && reflect.PtrTo(kr.Type()).Implements(textMarshalerType) {
+ b, err := kr.Addr().Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return "", fmt.Errorf("toml: cannot marshal map key: %w", err)
+ }
+ return string(b), nil
+ }
+ switch kr.Kind() {
+ case reflect.String:
+ return kr.String(), nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return strconv.FormatInt(kr.Int(), 10), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return strconv.FormatUint(kr.Uint(), 10), nil
+ case reflect.Float32:
+ return strconv.FormatFloat(kr.Float(), 'f', -1, 32), nil
+ case reflect.Float64:
+ return strconv.FormatFloat(kr.Float(), 'f', -1, 64), nil
+ default:
+ return "", fmt.Errorf("toml: cannot encode a map with key type %s", k.Type())
+ }
}
-type entry struct {
- Key string
- Value reflect.Value
- Options valueOptions
+// encPlanField is the static encoding information of one field of a struct.
+type encPlanField struct {
+ name string
+ index []int
+ depth int
+ options valueOptions
}
-type table struct {
- kvs []entry
- tables []entry
+// encPlan caches the per-type information needed to encode a struct:
+// flattened fields with parsed tags, in order of definition, with shadowed
+// duplicates already removed.
+type encPlan struct {
+ fields []encPlanField
}
-func (t *table) pushKV(k string, v reflect.Value, options valueOptions) {
- for _, e := range t.kvs {
- if e.Key == k {
- return
- }
- }
-
- t.kvs = append(t.kvs, entry{Key: k, Value: v, Options: options})
-}
+var encPlans sync.Map // reflect.Type -> *encPlan
-func (t *table) pushTable(k string, v reflect.Value, options valueOptions) {
- for _, e := range t.tables {
- if e.Key == k {
- return
- }
+func encPlanForType(t reflect.Type) *encPlan {
+ if plan, ok := encPlans.Load(t); ok {
+ return plan.(*encPlan)
}
- t.tables = append(t.tables, entry{Key: k, Value: v, Options: options})
+ plan := &encPlan{}
+ visited := map[reflect.Type]bool{}
+ buildEncPlan(plan, t, nil, 0, visited)
+ dedupEncPlan(plan)
+ encPlans.Store(t, plan)
+ return plan
}
-func walkStruct(ctx encoderCtx, t *table, v reflect.Value) {
- // TODO: cache this
- typ := v.Type()
- for i := 0; i < typ.NumField(); i++ {
- fieldType := typ.Field(i)
-
- // only consider exported fields
- if fieldType.PkgPath != "" {
- continue
- }
+func buildEncPlan(plan *encPlan, t reflect.Type, prefix []int, depth int, visited map[reflect.Type]bool) {
+ if visited[t] {
+ return
+ }
+ visited[t] = true
+ defer delete(visited, t)
- tag := fieldType.Tag.Get("toml")
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
- // special field name to skip field
+ tag, tagged := f.Tag.Lookup("toml")
if tag == "-" {
continue
}
- k, opts := parseTag(tag)
- if !isValidName(k) {
- k = ""
- }
-
- f := v.Field(i)
-
- if k == "" {
- if fieldType.Anonymous {
- if fieldType.Type.Kind() == reflect.Struct {
- walkStruct(ctx, t, f)
- } else if fieldType.Type.Kind() == reflect.Ptr && !f.IsNil() && f.Elem().Kind() == reflect.Struct {
- walkStruct(ctx, t, f.Elem())
+ name := f.Name
+ var opts valueOptions
+ if tagged {
+ parts := strings.Split(tag, ",")
+ if parts[0] != "" {
+ name = parts[0]
+ }
+ for _, opt := range parts[1:] {
+ switch opt {
+ case "multiline":
+ opts.multiline = true
+ case "inline":
+ opts.inline = true
+ case "omitempty":
+ opts.omitempty = true
+ case "omitzero":
+ opts.omitzero = true
+ case "commented":
+ opts.commented = true
}
- continue
- } else {
- k = fieldType.Name
}
}
-
- if isNil(f) {
- continue
+ // Standalone boolean tags, e.g. multiline:"true".
+ const tagTrue = "true"
+ if f.Tag.Get("multiline") == tagTrue {
+ opts.multiline = true
}
-
- options := valueOptions{
- multiline: opts.multiline,
- omitempty: opts.omitempty,
- commented: opts.commented,
- comment: fieldType.Tag.Get("comment"),
+ if f.Tag.Get("inline") == tagTrue {
+ opts.inline = true
}
-
- if opts.inline || !willConvertToTableOrArrayTable(ctx, f) {
- t.pushKV(k, f, options)
- } else {
- t.pushTable(k, f, options)
+ if f.Tag.Get("commented") == tagTrue {
+ opts.commented = true
}
- }
-}
+ opts.comment = f.Tag.Get("comment")
-func (enc *Encoder) encodeStruct(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
- var t table
+ index := make([]int, 0, len(prefix)+1)
+ index = append(index, prefix...)
+ index = append(index, i)
- walkStruct(ctx, &t, v)
+ if f.Anonymous {
+ ft := f.Type
+ if ft.Kind() == reflect.Ptr {
+ ft = ft.Elem()
+ }
+ if ft.Kind() == reflect.Struct && (!tagged || tagName(tag) == "") {
+ buildEncPlan(plan, ft, index, depth+1, visited)
+ continue
+ }
+ if f.PkgPath != "" && ft.Kind() != reflect.Interface {
+ continue
+ }
+ } else if f.PkgPath != "" {
+ // unexported
+ continue
+ }
- return enc.encodeTable(b, ctx, t)
+ plan.fields = append(plan.fields, encPlanField{
+ name: name,
+ index: index,
+ depth: depth,
+ options: opts,
+ })
+ }
}
-func (enc *Encoder) encodeComment(indent int, comment string, b []byte) []byte {
- for len(comment) > 0 {
- var line string
- idx := strings.IndexByte(comment, '\n')
- if idx >= 0 {
- line = comment[:idx]
- comment = comment[idx+1:]
+// dedupEncPlan removes the fields shadowed by another one with the same
+// name (the shallowest wins), keeping the order of first appearance.
+func dedupEncPlan(plan *encPlan) {
+ byName := make(map[string]int, len(plan.fields))
+ drop := false
+ for i := range plan.fields {
+ f := &plan.fields[i]
+ j, seen := byName[f.name]
+ if !seen {
+ byName[f.name] = i
+ continue
+ }
+ drop = true
+ // Shallowest wins; on equal depth, the first in order wins.
+ if f.depth < plan.fields[j].depth {
+ plan.fields[j].name = ""
+ byName[f.name] = i
} else {
- line = comment
- comment = ""
+ f.name = ""
}
- b = enc.indent(indent, b)
- b = append(b, "# "...)
- b = append(b, line...)
- b = append(b, '\n')
}
- return b
-}
-
-func isValidName(s string) bool {
- if s == "" {
- return false
+ if !drop {
+ return
}
- for _, c := range s {
- switch {
- case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
- // Backslash and quote chars are reserved, but
- // otherwise any punctuation chars are allowed
- // in a tag name.
- case !unicode.IsLetter(c) && !unicode.IsDigit(c):
- return false
+ out := plan.fields[:0]
+ for _, f := range plan.fields {
+ if f.name != "" {
+ out = append(out, f)
}
}
- return true
+ plan.fields = out
}
-type tagOptions struct {
- multiline bool
- inline bool
- omitempty bool
- commented bool
-}
-
-func parseTag(tag string) (string, tagOptions) {
- opts := tagOptions{}
-
- idx := strings.Index(tag, ",")
- if idx == -1 {
- return tag, opts
- }
+// collectStructEntries appends the entries of a struct, flattening embedded
+// structs in place.
+func (e *encoderState) collectStructEntries(entries *[]entry, v reflect.Value) {
+ plan := encPlanForType(v.Type())
- raw := tag[idx+1:]
- tag = string(tag[:idx])
- for raw != "" {
- var o string
- i := strings.Index(raw, ",")
- if i >= 0 {
- o, raw = raw[:i], raw[i+1:]
- } else {
- o, raw = raw, ""
- }
- switch o {
- case "multiline":
- opts.multiline = true
- case "inline":
- opts.inline = true
- case "omitempty":
- opts.omitempty = true
- case "commented":
- opts.commented = true
+ for i := range plan.fields {
+ f := &plan.fields[i]
+ fv, ok := fieldByIndexSkipNil(v, f.index)
+ if !ok {
+ // nil embedded pointer on the way: skipped
+ continue
}
- }
-
- return tag, opts
-}
-
-func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, error) {
- var err error
-
- ctx.shiftKey()
-
- if ctx.insideKv || (ctx.inline && !ctx.isRoot()) {
- return enc.encodeTableInline(b, ctx, t)
- }
- if !ctx.skipTableHeader {
- b, err = enc.encodeTableHeader(ctx, b)
- if err != nil {
- return nil, err
+ // Anonymous interface fields that are nil are skipped.
+ if fv.Kind() == reflect.Interface && fv.IsNil() {
+ continue
}
-
- if enc.indentTables && len(ctx.parentKey) > 0 {
- ctx.indent++
+ // nil values in struct fields are skipped
+ if (fv.Kind() == reflect.Ptr || fv.Kind() == reflect.Map) && fv.IsNil() {
+ continue
}
- }
- ctx.skipTableHeader = false
- hasNonEmptyKV := false
- for _, kv := range t.kvs {
- if shouldOmitEmpty(kv.Options, kv.Value) {
+ if f.options.omitempty && isEmptyValue(fv) {
continue
}
- hasNonEmptyKV = true
-
- ctx.setKey(kv.Key)
- ctx2 := ctx
- ctx2.commented = kv.Options.commented || ctx2.commented
-
- b, err = enc.encodeKv(b, ctx2, kv.Options, kv.Value)
- if err != nil {
- return nil, err
+ if f.options.omitzero && isZeroValue(fv) {
+ continue
}
- b = append(b, '\n')
+ *entries = append(*entries, entry{key: f.name, value: fv, options: f.options})
}
+}
- first := true
- for _, table := range t.tables {
- if shouldOmitEmpty(table.Options, table.Value) {
- continue
- }
- if first {
- first = false
- if hasNonEmptyKV {
- b = append(b, '\n')
+// fieldByIndexSkipNil returns the field at the given index path, reporting
+// false if a nil embedded pointer is found on the way.
+func fieldByIndexSkipNil(v reflect.Value, index []int) (reflect.Value, bool) {
+ for i, x := range index {
+ if i > 0 {
+ for v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return v, false
+ }
+ v = v.Elem()
}
- } else {
- b = append(b, "\n"...)
}
+ v = v.Field(x)
+ }
+ return v, true
+}
- ctx.setKey(table.Key)
-
- ctx.options = table.Options
- ctx2 := ctx
- ctx2.commented = ctx2.commented || ctx.options.commented
+func tagName(tag string) string {
+ if idx := strings.IndexByte(tag, ','); idx >= 0 {
+ return tag[:idx]
+ }
+ return tag
+}
- b, err = enc.encode(b, ctx2, table.Value)
- if err != nil {
- return nil, err
+// isEmptyValue implements the omitempty rules.
+func isEmptyValue(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.String:
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Map, reflect.Slice, reflect.Array:
+ return v.Len() == 0
+ case reflect.Ptr, reflect.Interface:
+ return v.IsNil()
+ case reflect.Struct:
+ // Structs that encode as a scalar value (time.Time, the local
+ // date/time types, or any TextMarshaler) are empty only when they
+ // equal their zero value; their fields are typically unexported, so
+ // recursing into them would be meaningless.
+ if encPropsForType(v.Type()).isValue {
+ return v.IsZero()
}
+ // Plain structs encode as tables and are empty when every field that
+ // would be encoded is itself empty. This matches the recursive rule
+ // used before the encoder rewrite and, in particular, treats a
+ // non-nil but empty map or slice as empty (reflect.Value.IsZero does
+ // not, which would otherwise emit an empty table header).
+ return isEmptyStruct(v)
+ default:
+ return false
}
-
- return b, nil
}
-func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte, error) {
- var err error
-
- b = append(b, '{')
-
- first := true
- for _, kv := range t.kvs {
- if shouldOmitEmpty(kv.Options, kv.Value) {
+// isEmptyStruct reports whether all of a table-valued struct's encodable
+// fields are empty per isEmptyValue. It mirrors the field selection done by
+// collectStructEntries (embedded flattening, shadowing, and "-" skips) so the
+// emptiness decision matches what would actually be encoded.
+func isEmptyStruct(v reflect.Value) bool {
+ plan := encPlanForType(v.Type())
+ for i := range plan.fields {
+ fv, ok := fieldByIndexSkipNil(v, plan.fields[i].index)
+ if !ok {
+ // A nil embedded pointer along the path contributes nothing.
continue
}
-
- if first {
- first = false
- } else {
- b = append(b, `, `...)
- }
-
- ctx.setKey(kv.Key)
-
- b, err = enc.encodeKv(b, ctx, kv.Options, kv.Value)
- if err != nil {
- return nil, err
+ if !isEmptyValue(fv) {
+ return false
}
}
+ return true
+}
- if len(t.tables) > 0 {
- panic("inline table cannot contain nested tables, only key-values")
+// isZeroValue implements the omitzero rules: the type's own IsZero() when
+// implemented, the reflect zero value otherwise.
+func isZeroValue(v reflect.Value) bool {
+ if v.Type().Implements(isZeroerType) {
+ return v.Interface().(isZeroer).IsZero()
}
-
- b = append(b, "}"...)
-
- return b, nil
+ if v.CanAddr() && reflect.PtrTo(v.Type()).Implements(isZeroerType) {
+ return v.Addr().Interface().(isZeroer).IsZero()
+ }
+ if !v.CanAddr() && reflect.PtrTo(v.Type()).Implements(isZeroerType) {
+ tmp := reflect.New(v.Type())
+ tmp.Elem().Set(v)
+ return tmp.Interface().(isZeroer).IsZero()
+ }
+ return v.IsZero()
}
-func willConvertToTable(ctx encoderCtx, v reflect.Value) bool {
- if !v.IsValid() {
- return false
+// appendKey emits a key, quoted only if necessary.
+func (e *encoderState) appendKey(b []byte, key string) []byte {
+ if isBareKey(key) {
+ return append(b, key...)
}
- if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) {
+ return e.appendString(b, key)
+}
+
+func isBareKey(key string) bool {
+ if len(key) == 0 {
return false
}
-
- t := v.Type()
- switch t.Kind() {
- case reflect.Map, reflect.Struct:
- return !ctx.inline
- case reflect.Interface:
- return willConvertToTable(ctx, v.Elem())
- case reflect.Ptr:
- if v.IsNil() {
+ for _, c := range []byte(key) {
+ if !isUnquotedKeyByte(c) {
return false
}
-
- return willConvertToTable(ctx, v.Elem())
- default:
- return false
}
+ return true
}
-func willConvertToTableOrArrayTable(ctx encoderCtx, v reflect.Value) bool {
- if ctx.insideKv {
- return false
- }
+func isUnquotedKeyByte(c byte) bool {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_'
+}
+
+// appendValue emits a TOML value.
+func (e *encoderState) appendValue(b []byte, v reflect.Value, opts valueOptions, indent int) ([]byte, error) {
t := v.Type()
- if t.Kind() == reflect.Interface {
- return willConvertToTableOrArrayTable(ctx, v.Elem())
+ // Special types take precedence over their kind.
+ switch t {
+ case timeType:
+ return v.Interface().(time.Time).AppendFormat(b, "2006-01-02T15:04:05.999999999Z07:00"), nil
+ case localDateType:
+ return append(b, v.Interface().(LocalDate).String()...), nil
+ case localTimeType:
+ return append(b, v.Interface().(LocalTime).String()...), nil
+ case localDateTimeType:
+ return append(b, v.Interface().(LocalDateTime).String()...), nil
+ case jsonNumberType:
+ if e.marshalJSONNumbers {
+ return appendJSONNumber(b, v.Interface().(json.Number))
+ }
}
- if t.Kind() == reflect.Slice || t.Kind() == reflect.Array {
- if v.Len() == 0 {
- // An empty slice should be a kv = [].
- return false
+ // A Marshaler reached through a value position (an array element or inline
+ // table member) splices its bytes verbatim. Everything (including the type
+ // check) lives in a separate method so this hot function keeps its default
+ // layout: when the opt-in interface is off, only the bool test runs here.
+ if e.marshalerOn {
+ if b2, done, err := e.appendMarshalerInline(b, v, t); done {
+ return b2, err
}
+ }
- for i := 0; i < v.Len(); i++ {
- t := willConvertToTable(ctx, v.Index(i))
-
- if !t {
- return false
- }
+ switch encPropsForType(t).text {
+ case 1:
+ if t.Kind() != reflect.String {
+ return e.appendTextMarshaler(b, v.Interface().(encoding.TextMarshaler))
}
-
- return true
+ case 2:
+ if v.CanAddr() {
+ return e.appendTextMarshaler(b, v.Addr().Interface().(encoding.TextMarshaler))
+ }
+ tmp := reflect.New(t)
+ tmp.Elem().Set(v)
+ return e.appendTextMarshaler(b, tmp.Interface().(encoding.TextMarshaler))
}
- return willConvertToTable(ctx, v)
+ switch v.Kind() {
+ case reflect.Ptr:
+ if v.IsNil() {
+ // nil pointers are encoded as the zero value of their element
+ // type.
+ return e.appendValue(b, reflect.Zero(t.Elem()), opts, indent)
+ }
+ return e.appendValue(b, v.Elem(), opts, indent)
+ case reflect.Interface:
+ if v.IsNil() {
+ return nil, errors.New("toml: cannot encode a nil interface")
+ }
+ return e.appendValue(b, v.Elem(), opts, indent)
+ case reflect.String:
+ s := v.String()
+ // The "multiline" option only takes effect when the string actually
+ // contains a newline. Wrapping a single-line value such as "2" in a
+ // """...""" block adds noise without improving readability, so it is
+ // emitted as a regular single-line string instead.
+ if opts.multiline && strings.IndexByte(s, '\n') >= 0 {
+ return e.appendMultilineString(b, s), nil
+ }
+ return e.appendString(b, s), nil
+ case reflect.Bool:
+ if v.Bool() {
+ return append(b, "true"...), nil
+ }
+ return append(b, "false"...), nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return strconv.AppendInt(b, v.Int(), 10), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ u := v.Uint()
+ if u > math.MaxInt64 {
+ return nil, fmt.Errorf("toml: cannot encode an unsigned integer above math.MaxInt64: %d", u)
+ }
+ return strconv.AppendUint(b, u, 10), nil
+ case reflect.Float32:
+ return appendFloat(b, v.Float(), 32), nil
+ case reflect.Float64:
+ return appendFloat(b, v.Float(), 64), nil
+ case reflect.Slice, reflect.Array:
+ return e.appendArray(b, v, opts, indent)
+ case reflect.Map:
+ return e.appendInlineTable(b, v, indent)
+ case reflect.Struct:
+ return e.appendInlineTable(b, v, indent)
+ default:
+ return nil, fmt.Errorf("toml: cannot encode value of type %s", v.Type())
+ }
}
-func (enc *Encoder) encodeSlice(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
- if v.Len() == 0 {
- b = append(b, "[]"...)
+var jsonNumberType = reflect.TypeOf(json.Number(""))
- return b, nil
+func appendJSONNumber(b []byte, n json.Number) ([]byte, error) {
+ if n == "" {
+ return append(b, '0'), nil
}
-
- if willConvertToTableOrArrayTable(ctx, v) {
- return enc.encodeSliceAsArrayTable(b, ctx, v)
+ if i, err := n.Int64(); err == nil {
+ return strconv.AppendInt(b, i, 10), nil
}
-
- return enc.encodeSliceAsArray(b, ctx, v)
+ f, err := n.Float64()
+ if err != nil {
+ return nil, fmt.Errorf("toml: cannot encode json.Number %q: %w", string(n), err)
+ }
+ return appendFloat(b, f, 64), nil
}
-// caller should have checked that v is a slice that only contains values that
-// encode into tables.
-func (enc *Encoder) encodeSliceAsArrayTable(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
- ctx.shiftKey()
-
- scratch := make([]byte, 0, 64)
-
- scratch = enc.commented(ctx.commented, scratch)
+func appendFloat(b []byte, f float64, bitSize int) []byte {
+ switch {
+ case math.IsNaN(f):
+ return append(b, "nan"...)
+ case math.IsInf(f, 1):
+ return append(b, "inf"...)
+ case math.IsInf(f, -1):
+ return append(b, "-inf"...)
+ }
+ start := len(b)
+ b = strconv.AppendFloat(b, f, 'f', -1, bitSize)
+ // TOML floats must have a fractional part or an exponent.
+ if !bytes.ContainsAny(b[start:], ".eE") {
+ b = append(b, ".0"...)
+ }
+ return b
+}
- if enc.indentTables {
- scratch = enc.indent(ctx.indent, scratch)
+func (e *encoderState) appendTextMarshaler(b []byte, m encoding.TextMarshaler) ([]byte, error) {
+ text, err := m.MarshalText()
+ if err != nil {
+ return nil, fmt.Errorf("toml: error calling MarshalText: %w", err)
}
+ return e.appendString(b, string(text)), nil
+}
- scratch = append(scratch, "[["...)
+// appendArray encodes a slice or array value.
+func (e *encoderState) appendArray(b []byte, v reflect.Value, opts valueOptions, indent int) ([]byte, error) {
+ multiline := opts.multiline || e.arraysMultiline
- for i, k := range ctx.parentKey {
- if i > 0 {
- scratch = append(scratch, '.')
+ b = append(b, '[')
+ if multiline && v.Len() > 0 {
+ for i := 0; i < v.Len(); i++ {
+ if i > 0 {
+ b = append(b, ',')
+ }
+ b = append(b, '\n')
+ for j := 0; j <= indent; j++ {
+ b = append(b, e.indentSymbol...)
+ }
+ var err error
+ b, err = e.appendValue(b, v.Index(i), valueOptions{}, indent+1)
+ if err != nil {
+ return nil, err
+ }
+ }
+ b = append(b, '\n')
+ for j := 0; j < indent; j++ {
+ b = append(b, e.indentSymbol...)
+ }
+ } else {
+ for i := 0; i < v.Len(); i++ {
+ if i > 0 {
+ b = append(b, ", "...)
+ }
+ var err error
+ b, err = e.appendValue(b, v.Index(i), valueOptions{}, indent)
+ if err != nil {
+ return nil, err
+ }
}
-
- scratch = enc.encodeKey(scratch, k)
}
+ return append(b, ']'), nil
+}
- scratch = append(scratch, "]]\n"...)
- ctx.skipTableHeader = true
-
- b = enc.encodeComment(ctx.indent, ctx.options.comment, b)
-
- if enc.indentTables {
- ctx.indent++
+// appendInlineTable encodes a map or a struct as an inline table.
+func (e *encoderState) appendInlineTable(b []byte, v reflect.Value, indent int) ([]byte, error) {
+ entries, err := e.collectEntries(v)
+ if err != nil {
+ return nil, err
}
- for i := 0; i < v.Len(); i++ {
- if i != 0 {
- b = append(b, "\n"...)
+ b = append(b, '{')
+ for i, ent := range entries {
+ if i > 0 {
+ b = append(b, ", "...)
}
-
- b = append(b, scratch...)
-
- var err error
- b, err = enc.encode(b, ctx, v.Index(i))
+ b = e.appendKey(b, ent.key)
+ b = append(b, " = "...)
+ // multiline strings are not allowed inside inline tables: they
+ // would break the single-line requirement.
+ opts := ent.options
+ opts.multiline = false
+ b, err = e.appendValue(b, ent.value, opts, indent)
if err != nil {
return nil, err
}
}
-
- return b, nil
+ e.putEntries(entries)
+ return append(b, '}'), nil
}
-func (enc *Encoder) encodeSliceAsArray(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
- multiline := ctx.options.multiline || enc.arraysMultiline
- separator := ", "
-
- b = append(b, '[')
-
- subCtx := ctx
- subCtx.options = valueOptions{}
-
- if multiline {
- separator = ",\n"
-
- b = append(b, '\n')
-
- subCtx.indent++
+// appendString encodes a string, using a literal string when possible and a
+// basic string otherwise.
+func (e *encoderState) appendString(b []byte, s string) []byte {
+ if canBeLiteral(s) {
+ b = append(b, '\'')
+ b = append(b, s...)
+ return append(b, '\'')
}
+ return appendBasicString(b, s)
+}
- var err error
- first := true
-
- for i := 0; i < v.Len(); i++ {
- if first {
- first = false
- } else {
- b = append(b, separator...)
- }
-
- if multiline {
- b = enc.indent(subCtx.indent, b)
- }
-
- b, err = enc.encode(b, subCtx, v.Index(i))
- if err != nil {
- return nil, err
+// canBeLiteral returns true when the string can be represented as a TOML
+// literal string: no control characters, no single quote, no newline.
+func canBeLiteral(s string) bool {
+ for i := 0; i < len(s); i++ {
+ c := s[i]
+ if c == '\'' || c == 0x7f || c < 0x20 {
+ return false
}
}
+ return utf8.ValidString(s)
+}
- if multiline {
- b = append(b, '\n')
- b = enc.indent(ctx.indent, b)
+// appendBasicString encodes a string as a TOML basic (double-quoted) string.
+func appendBasicString(b []byte, s string) []byte {
+ b = append(b, '"')
+ for i := 0; i < len(s); {
+ c := s[i]
+ switch {
+ case c == '"':
+ b = append(b, '\\', '"')
+ i++
+ case c == '\\':
+ b = append(b, '\\', '\\')
+ i++
+ case c == '\b':
+ b = append(b, '\\', 'b')
+ i++
+ case c == '\f':
+ b = append(b, '\\', 'f')
+ i++
+ case c == '\n':
+ b = append(b, '\\', 'n')
+ i++
+ case c == '\r':
+ b = append(b, '\\', 'r')
+ i++
+ case c == '\t':
+ b = append(b, '\\', 't')
+ i++
+ case c < 0x20 || c == 0x7f:
+ b = append(b, fmt.Sprintf("\\u%04X", c)...)
+ i++
+ default:
+ r, size := utf8.DecodeRuneInString(s[i:])
+ if r == utf8.RuneError && size == 1 {
+ // Replace invalid bytes by the replacement character.
+ b = append(b, fmt.Sprintf("\\u%04X", c)...)
+ i++
+ continue
+ }
+ b = append(b, s[i:i+size]...)
+ i += size
+ }
}
-
- b = append(b, ']')
-
- return b, nil
+ return append(b, '"')
}
-func (enc *Encoder) indent(level int, b []byte) []byte {
- for i := 0; i < level; i++ {
- b = append(b, enc.indentSymbol...)
+// appendMultilineString encodes a string as a TOML multi-line basic string.
+func appendMultilineString(b []byte, s string) []byte {
+ b = append(b, `"""`...)
+ b = append(b, '\n')
+ for i := 0; i < len(s); {
+ c := s[i]
+ switch {
+ case c == '"':
+ // Runs of three or more quotes must be escaped.
+ j := i
+ for j < len(s) && s[j] == '"' {
+ j++
+ }
+ if j-i >= 3 {
+ for ; i < j; i++ {
+ b = append(b, '\\', '"')
+ }
+ } else {
+ b = append(b, s[i:j]...)
+ i = j
+ }
+ case c == '\\':
+ b = append(b, '\\', '\\')
+ i++
+ case c == '\n':
+ b = append(b, '\n')
+ i++
+ case c == '\b':
+ b = append(b, '\\', 'b')
+ i++
+ case c == '\f':
+ b = append(b, '\\', 'f')
+ i++
+ case c == '\r':
+ b = append(b, '\\', 'r')
+ i++
+ case c == '\t':
+ b = append(b, '\t')
+ i++
+ case c < 0x20 || c == 0x7f:
+ b = append(b, fmt.Sprintf("\\u%04X", c)...)
+ i++
+ default:
+ r, size := utf8.DecodeRuneInString(s[i:])
+ if r == utf8.RuneError && size == 1 {
+ b = append(b, fmt.Sprintf("\\u%04X", c)...)
+ i++
+ continue
+ }
+ b = append(b, s[i:i+size]...)
+ i += size
+ }
}
+ return append(b, `"""`...)
+}
- return b
+func (e *encoderState) appendMultilineString(b []byte, s string) []byte {
+ return appendMultilineString(b, s)
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/strict.go b/vendor/github.com/pelletier/go-toml/v2/strict.go
index 802e7e4d..b58571df 100644
--- a/vendor/github.com/pelletier/go-toml/v2/strict.go
+++ b/vendor/github.com/pelletier/go-toml/v2/strict.go
@@ -1,7 +1,6 @@
package toml
import (
- "github.com/pelletier/go-toml/v2/internal/danger"
"github.com/pelletier/go-toml/v2/internal/tracker"
"github.com/pelletier/go-toml/v2/unstable"
)
@@ -12,66 +11,63 @@ type strict struct {
// Tracks the current key being processed.
key tracker.KeyTracker
- missing []unstable.ParserError
+ missing []decodeError
}
-func (s *strict) EnterTable(node *unstable.Node) {
- if !s.Enabled {
- return
- }
-
- s.key.UpdateTable(node)
+// decodeError is the information needed to materialize a DecodeError once the
+// whole document is available.
+type decodeError struct {
+ highlight unstable.Range
+ key Key
+ message string
}
-func (s *strict) EnterArrayTable(node *unstable.Node) {
- if !s.Enabled {
- return
- }
-
- s.key.UpdateArrayTable(node)
-}
-
-func (s *strict) EnterKeyValue(node *unstable.Node) {
- if !s.Enabled {
- return
- }
-
- s.key.Push(node)
+// Reset clears the state of the tracker so it can be reused for another
+// document.
+func (s *strict) Reset() {
+ s.key = tracker.KeyTracker{}
+ s.missing = s.missing[:0]
}
-func (s *strict) ExitKeyValue(node *unstable.Node) {
+// EnterTable is called when a new table or array table expression starts
+// being processed.
+func (s *strict) EnterTable(node *unstable.Node) {
if !s.Enabled {
return
}
-
- s.key.Pop(node)
+ s.key.UpdateTable(node)
}
+// MissingTable is called when a table is present in the document but has no
+// corresponding field in the target.
func (s *strict) MissingTable(node *unstable.Node) {
if !s.Enabled {
return
}
-
- s.missing = append(s.missing, unstable.ParserError{
- Highlight: keyLocation(node),
- Message: "missing table",
- Key: s.key.Key(),
+ s.missing = append(s.missing, decodeError{
+ highlight: keyLocation(node),
+ key: s.key.Key(),
+ message: "missing table",
})
}
+// MissingField is called when a key-value is present in the document but has
+// no corresponding field in the target.
func (s *strict) MissingField(node *unstable.Node) {
if !s.Enabled {
return
}
-
- s.missing = append(s.missing, unstable.ParserError{
- Highlight: keyLocation(node),
- Message: "missing field",
- Key: s.key.Key(),
+ s.key.Push(node)
+ s.missing = append(s.missing, decodeError{
+ highlight: keyLocation(node),
+ key: s.key.Key(),
+ message: "unknown field",
})
+ s.key.Pop(node)
}
-func (s *strict) Error(doc []byte) error {
+// Error returns the cumulated StrictMissingError for the document, or nil.
+func (s *strict) Error(document []byte) error {
if !s.Enabled || len(s.missing) == 0 {
return nil
}
@@ -81,14 +77,16 @@ func (s *strict) Error(doc []byte) error {
}
for _, derr := range s.missing {
- derr := derr
- err.Errors = append(err.Errors, *wrapDecodeError(doc, &derr))
+ highlight := document[derr.highlight.Offset : derr.highlight.Offset+derr.highlight.Length]
+ err.Errors = append(err.Errors, *newDecodeError(document, highlight, derr.key, derr.message))
}
return err
}
-func keyLocation(node *unstable.Node) []byte {
+// keyLocation returns the range of the document covering all the parts of
+// the key of the given node.
+func keyLocation(node *unstable.Node) unstable.Range {
k := node.Key()
hasOne := k.Next()
@@ -96,12 +94,15 @@ func keyLocation(node *unstable.Node) []byte {
panic("should not be called with empty key")
}
- start := k.Node().Data
- end := k.Node().Data
+ start := k.Node().Raw
+ end := start
for k.Next() {
- end = k.Node().Data
+ end = k.Node().Raw
}
- return danger.BytesRange(start, end)
+ return unstable.Range{
+ Offset: start.Offset,
+ Length: end.Offset + end.Length - start.Offset,
+ }
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/test-go-versions.sh b/vendor/github.com/pelletier/go-toml/v2/test-go-versions.sh
new file mode 100644
index 00000000..5fe5c777
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/test-go-versions.sh
@@ -0,0 +1,597 @@
+#!/usr/bin/env bash
+
+set -uo pipefail
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# Go versions to test (1.11 through 1.26)
+GO_VERSIONS=(
+ "1.11"
+ "1.12"
+ "1.13"
+ "1.14"
+ "1.15"
+ "1.16"
+ "1.17"
+ "1.18"
+ "1.19"
+ "1.20"
+ "1.21"
+ "1.22"
+ "1.23"
+ "1.24"
+ "1.25"
+ "1.26"
+)
+
+# Default values
+PARALLEL=true
+VERBOSE=false
+OUTPUT_DIR="test-results"
+DOCKER_TIMEOUT="10m"
+
+usage() {
+ cat << EOF
+Usage: $0 [OPTIONS] [GO_VERSIONS...]
+
+Test go-toml across multiple Go versions using Docker containers.
+
+The script reports the lowest continuous supported Go version (where all subsequent
+versions pass) and only exits with non-zero status if either of the two most recent
+Go versions fail, indicating immediate attention is needed.
+
+Note: For Go versions < 1.21, the script automatically updates go.mod to match the
+target version, but older versions may still fail due to missing standard library
+features (e.g., the 'slices' package introduced in Go 1.21).
+
+OPTIONS:
+ -h, --help Show this help message
+ -s, --sequential Run tests sequentially instead of in parallel
+ -v, --verbose Enable verbose output
+ -o, --output DIR Output directory for test results (default: test-results)
+ -t, --timeout TIME Docker timeout for each test (default: 10m)
+ --list List available Go versions and exit
+
+ARGUMENTS:
+ GO_VERSIONS Specific Go versions to test (default: all supported versions)
+ Examples: 1.21 1.22 1.23
+
+EXAMPLES:
+ $0 # Test all Go versions in parallel
+ $0 --sequential # Test all Go versions sequentially
+ $0 1.21 1.22 1.23 # Test specific versions
+ $0 --verbose --output ./results 1.25 1.26 # Verbose output to custom directory
+
+EXIT CODES:
+ 0 Recent Go versions pass (good compatibility)
+ 1 Recent Go versions fail (needs attention) or script error
+
+EOF
+}
+
+log() {
+ echo -e "${BLUE}[$(date +'%H:%M:%S')]${NC} $*" >&2
+}
+
+log_success() {
+ echo -e "${GREEN}[$(date +'%H:%M:%S')] ✓${NC} $*" >&2
+}
+
+log_error() {
+ echo -e "${RED}[$(date +'%H:%M:%S')] ✗${NC} $*" >&2
+}
+
+log_warning() {
+ echo -e "${YELLOW}[$(date +'%H:%M:%S')] ⚠${NC} $*" >&2
+}
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ -s|--sequential)
+ PARALLEL=false
+ shift
+ ;;
+ -v|--verbose)
+ VERBOSE=true
+ shift
+ ;;
+ -o|--output)
+ OUTPUT_DIR="$2"
+ shift 2
+ ;;
+ -t|--timeout)
+ DOCKER_TIMEOUT="$2"
+ shift 2
+ ;;
+ --list)
+ echo "Available Go versions:"
+ printf '%s\n' "${GO_VERSIONS[@]}"
+ exit 0
+ ;;
+ -*)
+ echo "Unknown option: $1" >&2
+ usage
+ exit 1
+ ;;
+ *)
+ # Remaining arguments are Go versions
+ break
+ ;;
+ esac
+done
+
+# If specific versions provided, use those instead of defaults
+if [[ $# -gt 0 ]]; then
+ GO_VERSIONS=("$@")
+fi
+
+# Validate Go versions
+for version in "${GO_VERSIONS[@]}"; do
+ if ! [[ "$version" =~ ^1\.(1[1-9]|2[0-6])$ ]]; then
+ log_error "Invalid Go version: $version. Supported versions: 1.11-1.26"
+ exit 1
+ fi
+done
+
+# Check if Docker is available
+if ! command -v docker &> /dev/null; then
+ log_error "Docker is required but not installed or not in PATH"
+ exit 1
+fi
+
+# Check if Docker daemon is running
+if ! docker info &> /dev/null; then
+ log_error "Docker daemon is not running"
+ exit 1
+fi
+
+# Create output directory
+mkdir -p "$OUTPUT_DIR"
+
+# Function to test a single Go version
+test_go_version() {
+ local go_version="$1"
+ local container_name="go-toml-test-${go_version}"
+ local result_file="${OUTPUT_DIR}/go-${go_version}.txt"
+ local dockerfile_content
+
+ log "Testing Go $go_version..."
+
+ # Create a temporary Dockerfile for this version
+ # For Go versions < 1.21, we need to update go.mod to match the Go version
+ local needs_go_mod_update=false
+ if [[ $(echo "$go_version 1.21" | tr ' ' '\n' | sort -V | head -n1) == "$go_version" && "$go_version" != "1.21" ]]; then
+ needs_go_mod_update=true
+ fi
+
+ dockerfile_content="FROM golang:${go_version}-alpine
+
+# Install git (required for go mod)
+RUN apk add --no-cache git
+
+# Set working directory
+WORKDIR /app
+
+# Copy source code
+COPY . ."
+
+ # Add go.mod update step for older Go versions
+ if [[ "$needs_go_mod_update" == true ]]; then
+ dockerfile_content="$dockerfile_content
+
+# Update go.mod to match Go version (required for Go < 1.21)
+RUN if [ -f go.mod ]; then sed -i 's/^go [0-9]\\+\\.[0-9]\\+\\(\\.[0-9]\\+\\)\\?/go $go_version/' go.mod; fi
+
+# Note: Go versions < 1.21 may fail due to missing standard library packages (e.g., slices)
+# This is expected for projects that use Go 1.21+ features"
+ fi
+
+ dockerfile_content="$dockerfile_content
+
+# Run tests
+CMD [\"sh\", \"-c\", \"go version && echo '--- Running go test ./... ---' && go test ./...\"]"
+
+ # Create temporary directory for this test
+ local temp_dir
+ temp_dir=$(mktemp -d)
+
+ # Copy source to temp directory (excluding test results and git)
+ rsync -a --exclude="$OUTPUT_DIR" --exclude=".git" --exclude="*.test" . "$temp_dir/"
+
+ # Create Dockerfile in temp directory
+ echo "$dockerfile_content" > "$temp_dir/Dockerfile"
+
+ # Build and run container
+ local exit_code=0
+ local output
+
+ if $VERBOSE; then
+ log "Building Docker image for Go $go_version..."
+ fi
+
+ # Capture both stdout and stderr, and the exit code
+ if output=$(cd "$temp_dir" && timeout "$DOCKER_TIMEOUT" docker build -t "$container_name" . 2>&1 && \
+ timeout "$DOCKER_TIMEOUT" docker run --rm "$container_name" 2>&1); then
+ log_success "Go $go_version: PASSED"
+ echo "PASSED" > "${result_file}.status"
+ else
+ exit_code=$?
+ log_error "Go $go_version: FAILED (exit code: $exit_code)"
+ echo "FAILED" > "${result_file}.status"
+ fi
+
+ # Save full output
+ echo "$output" > "$result_file"
+
+ # Clean up
+ docker rmi "$container_name" &> /dev/null || true
+ rm -rf "$temp_dir"
+
+ if $VERBOSE; then
+ echo "--- Go $go_version output ---"
+ echo "$output"
+ echo "--- End Go $go_version output ---"
+ fi
+
+ return $exit_code
+}
+
+# Function to run tests in parallel
+run_parallel() {
+ local pids=()
+ local failed_versions=()
+
+ log "Starting parallel tests for ${#GO_VERSIONS[@]} Go versions..."
+
+ # Start all tests in background
+ for version in "${GO_VERSIONS[@]}"; do
+ test_go_version "$version" &
+ pids+=($!)
+ done
+
+ # Wait for all tests to complete
+ for i in "${!pids[@]}"; do
+ local pid=${pids[$i]}
+ local version=${GO_VERSIONS[$i]}
+
+ if ! wait $pid; then
+ failed_versions+=("$version")
+ fi
+ done
+
+ return ${#failed_versions[@]}
+}
+
+# Function to run tests sequentially
+run_sequential() {
+ local failed_versions=()
+
+ log "Starting sequential tests for ${#GO_VERSIONS[@]} Go versions..."
+
+ for version in "${GO_VERSIONS[@]}"; do
+ if ! test_go_version "$version"; then
+ failed_versions+=("$version")
+ fi
+ done
+
+ return ${#failed_versions[@]}
+}
+
+# Main execution
+main() {
+ local start_time
+ start_time=$(date +%s)
+
+ log "Starting Go version compatibility tests..."
+ log "Testing versions: ${GO_VERSIONS[*]}"
+ log "Output directory: $OUTPUT_DIR"
+ log "Parallel execution: $PARALLEL"
+
+ local failed_count
+ if $PARALLEL; then
+ run_parallel
+ failed_count=$?
+ else
+ run_sequential
+ failed_count=$?
+ fi
+
+ local end_time
+ end_time=$(date +%s)
+ local duration=$((end_time - start_time))
+
+ # Collect results for display
+ local passed_versions=()
+ local failed_versions=()
+ local unknown_versions=()
+ local passed_count=0
+
+ for version in "${GO_VERSIONS[@]}"; do
+ local status_file="${OUTPUT_DIR}/go-${version}.txt.status"
+ if [[ -f "$status_file" ]]; then
+ local status
+ status=$(cat "$status_file")
+ if [[ "$status" == "PASSED" ]]; then
+ passed_versions+=("$version")
+ ((passed_count++))
+ else
+ failed_versions+=("$version")
+ fi
+ else
+ unknown_versions+=("$version")
+ fi
+ done
+
+ # Generate summary report
+ local summary_file="${OUTPUT_DIR}/summary.txt"
+ {
+ echo "Go Version Compatibility Test Summary"
+ echo "====================================="
+ echo "Date: $(date)"
+ echo "Duration: ${duration}s"
+ echo "Parallel: $PARALLEL"
+ echo ""
+ echo "Results:"
+
+ for version in "${GO_VERSIONS[@]}"; do
+ local status_file="${OUTPUT_DIR}/go-${version}.txt.status"
+ if [[ -f "$status_file" ]]; then
+ local status
+ status=$(cat "$status_file")
+ if [[ "$status" == "PASSED" ]]; then
+ echo " Go $version: ✓ PASSED"
+ else
+ echo " Go $version: ✗ FAILED"
+ fi
+ else
+ echo " Go $version: ? UNKNOWN (no status file)"
+ fi
+ done
+
+ echo ""
+ echo "Summary: $passed_count/${#GO_VERSIONS[@]} versions passed"
+
+ if [[ $failed_count -gt 0 ]]; then
+ echo ""
+ echo "Failed versions details:"
+ for version in "${failed_versions[@]}"; do
+ echo ""
+ echo "--- Go $version (FAILED) ---"
+ local result_file="${OUTPUT_DIR}/go-${version}.txt"
+ if [[ -f "$result_file" ]]; then
+ tail -n 30 "$result_file"
+ fi
+ done
+ fi
+ } > "$summary_file"
+
+ # Find lowest continuous supported version and check recent versions
+ local lowest_continuous_version=""
+ local recent_versions_failed=false
+
+ # Sort versions to ensure proper order
+ local sorted_versions=()
+ for version in "${GO_VERSIONS[@]}"; do
+ sorted_versions+=("$version")
+ done
+ # Sort versions numerically (1.11, 1.12, ..., 1.25)
+ IFS=$'\n' sorted_versions=($(sort -V <<< "${sorted_versions[*]}"))
+
+ # Find lowest continuous supported version (all versions from this point onwards pass)
+ for version in "${sorted_versions[@]}"; do
+ local status_file="${OUTPUT_DIR}/go-${version}.txt.status"
+ local all_subsequent_pass=true
+
+ # Check if this version and all subsequent versions pass
+ local found_current=false
+ for check_version in "${sorted_versions[@]}"; do
+ if [[ "$check_version" == "$version" ]]; then
+ found_current=true
+ fi
+
+ if [[ "$found_current" == true ]]; then
+ local check_status_file="${OUTPUT_DIR}/go-${check_version}.txt.status"
+ if [[ -f "$check_status_file" ]]; then
+ local status
+ status=$(cat "$check_status_file")
+ if [[ "$status" != "PASSED" ]]; then
+ all_subsequent_pass=false
+ break
+ fi
+ else
+ all_subsequent_pass=false
+ break
+ fi
+ fi
+ done
+
+ if [[ "$all_subsequent_pass" == true ]]; then
+ lowest_continuous_version="$version"
+ break
+ fi
+ done
+
+ # Check if the two most recent versions failed
+ local num_versions=${#sorted_versions[@]}
+ if [[ $num_versions -ge 2 ]]; then
+ local second_recent="${sorted_versions[$((num_versions-2))]}"
+ local most_recent="${sorted_versions[$((num_versions-1))]}"
+
+ local second_recent_status_file="${OUTPUT_DIR}/go-${second_recent}.txt.status"
+ local most_recent_status_file="${OUTPUT_DIR}/go-${most_recent}.txt.status"
+
+ local second_recent_failed=false
+ local most_recent_failed=false
+
+ if [[ -f "$second_recent_status_file" ]]; then
+ local status
+ status=$(cat "$second_recent_status_file")
+ if [[ "$status" != "PASSED" ]]; then
+ second_recent_failed=true
+ fi
+ else
+ second_recent_failed=true
+ fi
+
+ if [[ -f "$most_recent_status_file" ]]; then
+ local status
+ status=$(cat "$most_recent_status_file")
+ if [[ "$status" != "PASSED" ]]; then
+ most_recent_failed=true
+ fi
+ else
+ most_recent_failed=true
+ fi
+
+ if [[ "$second_recent_failed" == true || "$most_recent_failed" == true ]]; then
+ recent_versions_failed=true
+ fi
+ elif [[ $num_versions -eq 1 ]]; then
+ # Only one version tested, check if it's the most recent and failed
+ local only_version="${sorted_versions[0]}"
+ local only_status_file="${OUTPUT_DIR}/go-${only_version}.txt.status"
+
+ if [[ -f "$only_status_file" ]]; then
+ local status
+ status=$(cat "$only_status_file")
+ if [[ "$status" != "PASSED" ]]; then
+ recent_versions_failed=true
+ fi
+ else
+ recent_versions_failed=true
+ fi
+ fi
+
+ # Display summary
+ echo ""
+ log "Test completed in ${duration}s"
+ log "Summary report: $summary_file"
+
+ echo ""
+ echo "========================================"
+ echo " FINAL RESULTS"
+ echo "========================================"
+ echo ""
+
+ # Display passed versions
+ if [[ ${#passed_versions[@]} -gt 0 ]]; then
+ log_success "PASSED (${#passed_versions[@]}/${#GO_VERSIONS[@]}):"
+ # Sort passed versions for display
+ local sorted_passed=()
+ for version in "${sorted_versions[@]}"; do
+ for passed_version in "${passed_versions[@]}"; do
+ if [[ "$version" == "$passed_version" ]]; then
+ sorted_passed+=("$version")
+ break
+ fi
+ done
+ done
+ for version in "${sorted_passed[@]}"; do
+ echo -e " ${GREEN}✓${NC} Go $version"
+ done
+ echo ""
+ fi
+
+ # Display failed versions
+ if [[ ${#failed_versions[@]} -gt 0 ]]; then
+ log_error "FAILED (${#failed_versions[@]}/${#GO_VERSIONS[@]}):"
+ # Sort failed versions for display
+ local sorted_failed=()
+ for version in "${sorted_versions[@]}"; do
+ for failed_version in "${failed_versions[@]}"; do
+ if [[ "$version" == "$failed_version" ]]; then
+ sorted_failed+=("$version")
+ break
+ fi
+ done
+ done
+ for version in "${sorted_failed[@]}"; do
+ echo -e " ${RED}✗${NC} Go $version"
+ done
+ echo ""
+
+ # Show failure details
+ echo "========================================"
+ echo " FAILURE DETAILS"
+ echo "========================================"
+ echo ""
+
+ for version in "${sorted_failed[@]}"; do
+ echo -e "${RED}--- Go $version FAILURE LOGS (last 30 lines) ---${NC}"
+ local result_file="${OUTPUT_DIR}/go-${version}.txt"
+ if [[ -f "$result_file" ]]; then
+ tail -n 30 "$result_file" | sed 's/^/ /'
+ else
+ echo " No log file found: $result_file"
+ fi
+ echo ""
+ done
+ fi
+
+ # Display unknown versions
+ if [[ ${#unknown_versions[@]} -gt 0 ]]; then
+ log_warning "UNKNOWN (${#unknown_versions[@]}/${#GO_VERSIONS[@]}):"
+ for version in "${unknown_versions[@]}"; do
+ echo -e " ${YELLOW}?${NC} Go $version (no status file)"
+ done
+ echo ""
+ fi
+
+ echo "========================================"
+ echo " COMPATIBILITY SUMMARY"
+ echo "========================================"
+ echo ""
+
+ if [[ -n "$lowest_continuous_version" ]]; then
+ log_success "Lowest continuous supported version: Go $lowest_continuous_version"
+ echo " (All versions from Go $lowest_continuous_version onwards pass)"
+ else
+ log_error "No continuous version support found"
+ echo " (No version has all subsequent versions passing)"
+ fi
+
+ echo ""
+ echo "========================================"
+ echo "Full detailed logs available in: $OUTPUT_DIR"
+ echo "========================================"
+
+ # Determine exit code based on recent versions
+ if [[ "$recent_versions_failed" == true ]]; then
+ log_error "OVERALL RESULT: Recent Go versions failed - this needs attention!"
+ if [[ -n "$lowest_continuous_version" ]]; then
+ echo "Note: Continuous support starts from Go $lowest_continuous_version"
+ fi
+ exit 1
+ else
+ log_success "OVERALL RESULT: Recent Go versions pass - compatibility looks good!"
+ if [[ -n "$lowest_continuous_version" ]]; then
+ echo "Continuous support starts from Go $lowest_continuous_version"
+ fi
+ exit 0
+ fi
+}
+
+# Trap to clean up on exit
+cleanup() {
+ # Kill any remaining background processes
+ jobs -p | xargs -r kill 2>/dev/null || true
+
+ # Clean up any remaining Docker containers
+ docker ps -q --filter "name=go-toml-test-" | xargs -r docker stop 2>/dev/null || true
+ docker images -q --filter "reference=go-toml-test-*" | xargs -r docker rmi 2>/dev/null || true
+}
+
+trap cleanup EXIT
+
+# Run main function
+main
diff --git a/vendor/github.com/pelletier/go-toml/v2/toml.abnf b/vendor/github.com/pelletier/go-toml/v2/toml.abnf
index 473f3749..7647c4be 100644
--- a/vendor/github.com/pelletier/go-toml/v2/toml.abnf
+++ b/vendor/github.com/pelletier/go-toml/v2/toml.abnf
@@ -36,7 +36,7 @@ newline =/ %x0D.0A ; CRLF
comment-start-symbol = %x23 ; #
non-ascii = %x80-D7FF / %xE000-10FFFF
-non-eol = %x09 / %x20-7F / non-ascii
+non-eol = %x09 / %x20-7E / non-ascii
comment = comment-start-symbol *non-eol
@@ -74,12 +74,14 @@ escape = %x5C ; \
escape-seq-char = %x22 ; " quotation mark U+0022
escape-seq-char =/ %x5C ; \ reverse solidus U+005C
escape-seq-char =/ %x62 ; b backspace U+0008
+escape-seq-char =/ %x65 ; e escape U+001B
escape-seq-char =/ %x66 ; f form feed U+000C
escape-seq-char =/ %x6E ; n line feed U+000A
escape-seq-char =/ %x72 ; r carriage return U+000D
escape-seq-char =/ %x74 ; t tab U+0009
-escape-seq-char =/ %x75 4HEXDIG ; uXXXX U+XXXX
-escape-seq-char =/ %x55 8HEXDIG ; UXXXXXXXX U+XXXXXXXX
+escape-seq-char =/ %x78 2HEXDIG ; xHH U+00HH
+escape-seq-char =/ %x75 4HEXDIG ; uHHHH U+HHHH
+escape-seq-char =/ %x55 8HEXDIG ; UHHHHHHHH U+HHHHHHHH
;; Multiline Basic String
@@ -174,7 +176,7 @@ time-secfrac = "." 1*DIGIT
time-numoffset = ( "+" / "-" ) time-hour ":" time-minute
time-offset = "Z" / time-numoffset
-partial-time = time-hour ":" time-minute ":" time-second [ time-secfrac ]
+partial-time = time-hour ":" time-minute [ ":" time-second [ time-secfrac ] ]
full-date = date-fullyear "-" date-month "-" date-mday
full-time = partial-time time-offset
@@ -221,13 +223,14 @@ std-table-close = ws %x5D ; ] Right square bracket
;; Inline Table
-inline-table = inline-table-open [ inline-table-keyvals ] inline-table-close
+inline-table = inline-table-open [ inline-table-keyvals ] ws-comment-newline inline-table-close
-inline-table-open = %x7B ws ; {
-inline-table-close = ws %x7D ; }
-inline-table-sep = ws %x2C ws ; , Comma
+inline-table-open = %x7B ; {
+inline-table-close = %x7D ; }
+inline-table-sep = %x2C ; , Comma
-inline-table-keyvals = keyval [ inline-table-sep inline-table-keyvals ]
+inline-table-keyvals = ws-comment-newline keyval ws-comment-newline inline-table-sep inline-table-keyvals
+inline-table-keyvals =/ ws-comment-newline keyval ws-comment-newline [ inline-table-sep ]
;; Array Table
diff --git a/vendor/github.com/pelletier/go-toml/v2/types.go b/vendor/github.com/pelletier/go-toml/v2/types.go
index 3c6b8fe5..420f1982 100644
--- a/vendor/github.com/pelletier/go-toml/v2/types.go
+++ b/vendor/github.com/pelletier/go-toml/v2/types.go
@@ -6,9 +6,19 @@ import (
"time"
)
-var timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
-var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
-var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
-var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}(nil))
-var sliceInterfaceType = reflect.TypeOf([]interface{}(nil))
-var stringType = reflect.TypeOf("")
+// isZeroer is used to check whether a value is the zero value for its type,
+// as defined by the type itself.
+type isZeroer interface {
+ IsZero() bool
+}
+
+var isZeroerType = reflect.TypeOf(new(isZeroer)).Elem()
+
+var (
+ timeType = reflect.TypeOf(time.Time{})
+ textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
+ textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
+ mapStringInterfaceType = reflect.TypeOf(map[string]interface{}(nil))
+ sliceInterfaceType = reflect.TypeOf([]interface{}(nil))
+ stringType = reflect.TypeOf("")
+)
diff --git a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
index 189be525..d110243f 100644
--- a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
@@ -9,21 +9,70 @@ import (
"reflect"
"strconv"
"strings"
- "sync/atomic"
+ "sync"
"time"
- "github.com/pelletier/go-toml/v2/internal/danger"
"github.com/pelletier/go-toml/v2/internal/tracker"
"github.com/pelletier/go-toml/v2/unstable"
)
+// decoderPool recycles decoders (and their internal buffers: parser arena,
+// seen-tracker entries, scratch buffers) across calls to Unmarshal and
+// Decode.
+var decoderPool = sync.Pool{
+ New: func() interface{} { return &decoder{} },
+}
+
+func getDecoder(strictMode, unmarshalerInterface bool) *decoder {
+ d := decoderPool.Get().(*decoder)
+ d.reset()
+ d.strict.Enabled = strictMode
+ d.unmarshalerInterface = unmarshalerInterface
+ return d
+}
+
+func putDecoder(d *decoder) {
+ decoderPool.Put(d)
+}
+
+// reset clears the per-document state of the decoder, keeping the allocated
+// buffers for reuse.
+func (d *decoder) reset() {
+ d.seen.Reset()
+ d.tableKey = d.tableKey[:0]
+ d.skipUntilTable = false
+ d.path = d.path[:0]
+ d.captures = d.captures[:0]
+ d.captureIdx = -1
+ d.segIdx = d.segIdx[:0]
+ // Reuse the array-table counter slots across documents instead of
+ // deleting them: a zeroed slot is indistinguishable from an absent one,
+ // and keeping it alive means setArrayCount does not have to allocate a new
+ // *int every time the same path reappears. A safety valve bounds the table
+ // for adversarial inputs that introduce unboundedly many distinct paths.
+ if len(d.arrayCounts) > 1<<14 {
+ d.arrayCounts = nil
+ } else {
+ for _, p := range d.arrayCounts {
+ *p = 0
+ }
+ }
+ d.tableTarget = reflect.Value{}
+ d.tableTargetValid = false
+ d.tableFlush = d.tableFlush[:0]
+ d.tableParentSlot = slotWriter{}
+ d.keyParts = d.keyParts[:0]
+ d.strict.Reset()
+}
+
// Unmarshal deserializes a TOML document into a Go value.
//
// It is a shortcut for Decoder.Decode() with the default options.
func Unmarshal(data []byte, v interface{}) error {
- d := decoder{}
- d.p.Reset(data)
- return d.FromParser(v)
+ d := getDecoder(false, false)
+ err := d.unmarshal(data, v)
+ putDecoder(d)
+ return err
}
// Decoder reads and decode a TOML document from an input stream.
@@ -57,13 +106,18 @@ func (d *Decoder) DisallowUnknownFields() *Decoder {
// EnableUnmarshalerInterface allows to enable unmarshaler interface.
//
-// With this feature enabled, types implementing the unstable/Unmarshaler
+// With this feature enabled, types implementing the unstable.Unmarshaler
// interface can be decoded from any structure of the document. It allows types
// that don't have a straightforward TOML representation to provide their own
// decoding logic.
//
-// Currently, types can only decode from a single value. Tables and array tables
-// are not supported.
+// The UnmarshalTOML method receives raw TOML bytes:
+// - For single values: the raw value bytes (e.g., `"hello"` for a string)
+// - For tables: all key-value lines belonging to that table
+// - For inline tables/arrays: the raw bytes of the inline structure
+//
+// The unstable.RawMessage type can be used to capture raw TOML bytes for
+// later processing, similar to json.RawMessage.
//
// *Unstable:* This method does not follow the compatibility guarantees of
// semver. It can be changed or removed without a new major version being
@@ -120,164 +174,501 @@ func (d *Decoder) Decode(v interface{}) error {
return fmt.Errorf("toml: %w", err)
}
- dec := decoder{
- strict: strict{
- Enabled: d.strict,
- },
- unmarshalerInterface: d.unmarshalerInterface,
+ dec := getDecoder(d.strict, d.unmarshalerInterface)
+ err = dec.unmarshal(b, v)
+ putDecoder(dec)
+ return err
+}
+
+// pathPart is one part of the key path leading to a value. Parts that come
+// from the current table header only carry a name; parts that come from the
+// key of the current key-value expression also carry the AST node, and their
+// name is materialized lazily to avoid allocations.
+type pathPart struct {
+ name string
+ node *unstable.Node
+}
+
+// bytes returns the raw bytes of the key part.
+func (p *pathPart) bytes() []byte {
+ if p.node != nil {
+ return p.node.Data
+ }
+ return []byte(p.name)
+}
+
+// str returns the key part as a string, possibly allocating.
+func (p *pathPart) str() string {
+ if p.node != nil {
+ return string(p.node.Data)
}
- dec.p.Reset(b)
+ return p.name
+}
- return dec.FromParser(v)
+// rawCapture accumulates the raw bytes fed to a type implementing
+// unstable.Unmarshaler for a table target. The target is identified by the
+// parts of its key and the array-table indexes in effect when the capture
+// was created, so that it can be located again once the whole document has
+// been processed (the address of the target may change as slices grow).
+type rawCapture struct {
+ names []string
+ // indexes[i] is the index to use when reaching a slice or array right
+ // before consuming names[i]. indexes[len(names)] is the index of the
+ // element when the target is an element of an array table. -1 when not
+ // relevant.
+ indexes []int
+ buf []byte
}
type decoder struct {
- // Which parser instance in use for this decoding session.
p unstable.Parser
- // Flag indicating that the current expression is stashed.
- // If set to true, calling nextExpr will not actually pull a new expression
- // but turn off the flag instead.
- stashedExpr bool
+ // strict mode
+ strict strict
+
+ // toggles unmarshaler interface
+ unmarshalerInterface bool
- // Skip expressions until a table is found. This is set to true when a
- // table could not be created (missing field in map), so all KV expressions
- // need to be skipped.
+ // tracks the duplicate and type consistency of the keys
+ seen tracker.SeenTracker
+
+ // path of the current table header, as copied strings
+ tableKey []string
+
+ // true when the expressions under the current table header cannot be
+ // stored anywhere and should be skipped
skipUntilTable bool
- // Flag indicating that the current array/slice table should be cleared because
- // it is the first encounter of an array table.
- clearArrayTable bool
+ // scratch buffer for the key path of the current expression
+ path []pathPart
+
+ // raw captures for the unmarshaler interface, in order of first
+ // appearance. captureIdx is the index of the capture the current table
+ // belongs to, or -1.
+ captures []rawCapture
+ captureIdx int
+
+ // segIdx[i] records the array element index used when traversing a
+ // slice or array right before consuming the i-th part of the current
+ // table key. Reset for each table expression.
+ segIdx []int
+
+ // arrayCounts tracks the number of elements appended to fixed-size
+ // arrays used as array tables, keyed by the NUL-joined key parts.
+ // Values are pointer slots so that updating an existing path does not
+ // allocate a new key string.
+ arrayCounts map[string]*int
+
+ // Cached target of the current table, so that key-values do not need to
+ // walk the document structure from the root for every expression.
+ // tableFlush holds the write-backs to perform when leaving the table
+ // (for targets reached through map values, which are copies).
+ // tableParentSlot stores a replacement of the target itself (e.g. a nil
+ // map that was allocated) into its parent.
+ tableTarget reflect.Value
+ tableTargetValid bool
+ tableFlush []flushOp
+ tableParentSlot slotWriter
+
+ // strKey is a reusable string value used as map key, so that map
+ // operations with string keys do not need to allocate a boxed key for
+ // every access. It must be refreshed with stringMapKey immediately
+ // before each use: any recursive call may overwrite it.
+ strKey reflect.Value
+
+ // interned de-duplicates key strings: documents repeat the same keys
+ // over and over, and the table survives pooling, so repeated decodes
+ // of similar documents stop allocating key strings altogether.
+ interned map[string]string
+
+ // pathScratch is the buffer used by joinPath.
+ pathScratch []byte
+
+ // keyParts is the reusable buffer holding the decoded parts of the key of
+ // the current expression in the fused generic decode path.
+ keyParts [][]byte
+}
- // Tracks position in Go arrays.
- // This is used when decoding [[array tables]] into Go arrays. Given array
- // tables are separate TOML expression, we need to keep track of where we
- // are at in the Go array, as we can't just introspect its size.
- arrayIndexes map[reflect.Value]int
+// slotWriter remembers how to store a value at some location of the target
+// structure. Implemented as a struct instead of a closure to avoid
+// allocations.
+type slotWriter struct {
+ kind uint8 // 0: none, 1: slot.Set, 2: m.SetMapIndex(k, ...), 3: m.SetMapIndex(string key ks, ...)
+ slot reflect.Value
+ m reflect.Value
+ k reflect.Value
+ ks string
+}
- // Tracks keys that have been seen, with which type.
- seen tracker.SeenTracker
+func (d *decoder) storeSlot(s *slotWriter, nv reflect.Value) {
+ switch s.kind {
+ case 1:
+ if s.slot.CanSet() {
+ s.slot.Set(nv)
+ }
+ case 2:
+ s.m.SetMapIndex(s.k, nv)
+ case 3:
+ s.m.SetMapIndex(d.stringMapKey(s.ks), nv)
+ }
+}
- // Strict mode
- strict strict
+// flushOp stores val using w when the table is flushed.
+type flushOp struct {
+ w slotWriter
+ val reflect.Value
+}
- // Flag that enables/disables unmarshaler interface.
- unmarshalerInterface bool
+// flushTable performs the pending write-backs of the cached table target, in
+// reverse order so that inner copies land before their parents are stored.
+func (d *decoder) flushTable() {
+ for i := len(d.tableFlush) - 1; i >= 0; i-- {
+ d.storeSlot(&d.tableFlush[i].w, d.tableFlush[i].val)
+ }
+ d.tableFlush = d.tableFlush[:0]
+ d.tableTargetValid = false
+ d.tableParentSlot = slotWriter{}
+ d.tableTarget = reflect.Value{}
+}
- // Current context for the error.
- errorContext *errorContext
+// intern returns the string corresponding to the given bytes, reusing a
+// previous allocation when the same key has been seen before.
+func (d *decoder) intern(b []byte) string {
+ if s, ok := d.interned[string(b)]; ok { // does not allocate
+ return s
+ }
+ if d.interned == nil {
+ d.interned = make(map[string]string, 64)
+ } else if len(d.interned) >= 1<<14 {
+ // Safety valve for adversarial inputs: do not let the table grow
+ // without bounds.
+ for k := range d.interned {
+ delete(d.interned, k)
+ }
+ }
+ s := string(b)
+ d.interned[s] = s
+ return s
}
-type errorContext struct {
- Struct reflect.Type
- Field []int
+// partString returns the name of a path part, interning it when it comes
+// from the document.
+func (d *decoder) partString(p *pathPart) string {
+ if p.node != nil {
+ return d.intern(p.node.Data)
+ }
+ return p.name
}
-func (d *decoder) typeMismatchError(toml string, target reflect.Type) error {
- return fmt.Errorf("toml: %s", d.typeMismatchString(toml, target))
+// stringMapKey returns a reflect.Value holding the given string, reusing the
+// same allocation every time. The result must be used (the map operation
+// performed) before any recursive call, which may overwrite the buffer.
+func (d *decoder) stringMapKey(s string) reflect.Value {
+ if !d.strKey.IsValid() {
+ d.strKey = reflect.New(stringType).Elem()
+ }
+ d.strKey.SetString(s)
+ return d.strKey
}
-func (d *decoder) typeMismatchString(toml string, target reflect.Type) string {
- if d.errorContext != nil && d.errorContext.Struct != nil {
- ctx := d.errorContext
- f := ctx.Struct.FieldByIndex(ctx.Field)
- return fmt.Sprintf("cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type)
+// joinPath builds the NUL-joined representation of a key path in the
+// decoder's scratch buffer. The result is only valid until the next call.
+func (d *decoder) joinPath(parts []string) []byte {
+ d.pathScratch = d.pathScratch[:0]
+ for i, p := range parts {
+ if i > 0 {
+ d.pathScratch = append(d.pathScratch, 0)
+ }
+ d.pathScratch = append(d.pathScratch, p...)
}
- return fmt.Sprintf("cannot decode TOML %s into a Go value of type %s", toml, target)
+ return d.pathScratch
}
-func (d *decoder) expr() *unstable.Node {
- return d.p.Expression()
+// arrayCount returns the number of elements appended so far to the array
+// table at the given path.
+func (d *decoder) arrayCount(key []byte) int {
+ if d.arrayCounts == nil {
+ return 0
+ }
+ if p := d.arrayCounts[string(key)]; p != nil { // does not allocate
+ return *p
+ }
+ return 0
}
-func (d *decoder) nextExpr() bool {
- if d.stashedExpr {
- d.stashedExpr = false
- return true
+func (d *decoder) setArrayCount(key []byte, n int) {
+ if d.arrayCounts == nil {
+ d.arrayCounts = map[string]*int{}
+ }
+ if p := d.arrayCounts[string(key)]; p != nil { // does not allocate
+ *p = n
+ return
}
- return d.p.NextExpression()
+ v := n
+ d.arrayCounts[string(key)] = &v
}
-func (d *decoder) stashExpr() {
- d.stashedExpr = true
+// resetChildArrayCounts forgets the counts of all the array tables under
+// the given path, so that a new element starts fresh.
+func (d *decoder) resetChildArrayCounts(key []byte) {
+ if len(d.arrayCounts) == 0 {
+ return
+ }
+ for k, p := range d.arrayCounts {
+ // Prefix match without building the prefix string: same bytes as
+ // key, followed by the NUL separator.
+ if len(k) > len(key) && k[len(key)] == 0 && k[:len(key)] == string(key) {
+ // Zero instead of delete: the next element of the parent table
+ // will reuse the slot without allocating a new key.
+ *p = 0
+ }
+ }
}
-func (d *decoder) arrayIndex(shouldAppend bool, v reflect.Value) int {
- if d.arrayIndexes == nil {
- d.arrayIndexes = make(map[reflect.Value]int, 1)
+func (d *decoder) typeMismatchError(toml string, target reflect.Type, highlight []byte) error {
+ return &typeMismatchError{
+ toml: toml,
+ target: target,
+ highlight: highlight,
}
+}
- idx, ok := d.arrayIndexes[v]
+type typeMismatchError struct {
+ toml string
+ target reflect.Type
+ highlight []byte
+ // key is the TOML key being processed when the mismatch occurred. It is
+ // populated lazily as the error propagates back up to the key-value
+ // handler (see contextualizeError).
+ key Key
+}
- if !ok {
- d.arrayIndexes[v] = 0
- } else if shouldAppend {
- idx++
- d.arrayIndexes[v] = idx
+func (e *typeMismatchError) Error() string {
+ return fmt.Sprintf("cannot decode TOML %s into %s", e.toml, e.target)
+}
+
+// contextualizeError attaches the TOML key currently being processed to errors
+// raised while decoding a key-value expression, so that DecodeError.Key()
+// reports the offending key (e.g. on type mismatch errors). The current key is
+// reconstructed from d.path; when the table target is cached, d.path holds only
+// the key-value parts, so the table key prefix is prepended. This only runs on
+// the error path and adds no cost to successful decodes.
+func (d *decoder) contextualizeError(err error, withTableKey bool) error {
+ var mm *typeMismatchError
+ if errors.As(err, &mm) {
+ if mm.key == nil {
+ mm.key = d.currentKey(withTableKey)
+ }
+ return err
+ }
+ var perr *unstable.ParserError
+ if errors.As(err, &perr) {
+ if perr.Key == nil {
+ perr.Key = d.currentKey(withTableKey)
+ }
}
+ return err
+}
- return idx
+// currentKey reconstructs the full TOML key being processed from the decoder's
+// path. When withTableKey is true, d.path contains only the key-value parts
+// (the table target is cached) and the table key is prepended.
+func (d *decoder) currentKey(withTableKey bool) Key {
+ n := len(d.path)
+ if withTableKey {
+ n += len(d.tableKey)
+ }
+ key := make(Key, 0, n)
+ if withTableKey {
+ key = append(key, d.tableKey...)
+ }
+ for i := range d.path {
+ key = append(key, d.path[i].str())
+ }
+ return key
}
-func (d *decoder) FromParser(v interface{}) error {
+func (d *decoder) unmarshal(data []byte, v interface{}) error {
r := reflect.ValueOf(v)
if r.Kind() != reflect.Ptr {
return fmt.Errorf("toml: decoding can only be performed into a pointer, not %s", r.Kind())
}
-
if r.IsNil() {
- return fmt.Errorf("toml: decoding pointer target cannot be nil")
+ return errors.New("toml: decoding pointer target cannot be nil")
}
- r = r.Elem()
- if r.Kind() == reflect.Interface && r.IsNil() {
- newMap := map[string]interface{}{}
- r.Set(reflect.ValueOf(newMap))
+ root := r.Elem()
+
+ d.captureIdx = -1
+ d.p.Reset(data)
+
+ // Fully generic targets (interface{} or map[string]interface{}) are
+ // decoded straight into native Go maps and slices, with no reflection on
+ // the document structure at all. This covers the common "decode arbitrary
+ // TOML into a map" case, including every standard benchmark dataset.
+ if !d.unmarshalerInterface {
+ if k := root.Kind(); k == reflect.Interface || (k == reflect.Map && root.Type() == mapStringInterfaceType) {
+ return d.unmarshalFused(root, data)
+ }
}
- err := d.fromParser(r)
- if err == nil {
- return d.strict.Error(d.p.Data())
+ // When the root target itself implements the Unmarshaler interface, the
+ // whole document decodes into it. Open a capture spanning the entire
+ // document up front: the top-level key-values then flow through the
+ // existing capture branch and any tables attach to it via resumeCapture,
+ // so UnmarshalTOML receives the assembled document exactly once.
+ if d.unmarshalerInterface && hasUnmarshaler(root) {
+ d.startRootCapture()
}
- var e *unstable.ParserError
- if errors.As(err, &e) {
- return wrapDecodeError(d.p.Data(), e)
+ for d.p.NextExpression() {
+ err := d.handleRootExpression(d.p.Expression(), root)
+ if err != nil {
+ return d.wrapError(data, err)
+ }
+ }
+ if err := d.p.Error(); err != nil {
+ var perr *unstable.ParserError
+ if errors.As(err, &perr) {
+ return wrapDecodeError(data, perr)
+ }
+ return err
}
- return err
-}
+ d.flushTable()
-func (d *decoder) fromParser(root reflect.Value) error {
- for d.nextExpr() {
- err := d.handleRootExpression(d.expr(), root)
+ // Deliver the accumulated raw documents to the unmarshaler-interface
+ // targets.
+ for i := range d.captures {
+ nv, err := d.resolveCapture(root, &d.captures[i], 0, false)
if err != nil {
return err
}
+ if nv.IsValid() {
+ root.Set(nv)
+ }
+ }
+
+ // An empty document into a generic target still initializes it.
+ switch root.Kind() {
+ case reflect.Map:
+ if root.IsNil() {
+ root.Set(reflect.MakeMap(root.Type()))
+ }
+ case reflect.Interface:
+ if root.IsNil() {
+ root.Set(reflect.ValueOf(map[string]interface{}{}))
+ }
+ default:
}
- return d.p.Error()
+ return d.strict.Error(data)
+}
+
+// setAnyKey assigns the value of a key-value into the native map m, following
+// the (possibly dotted) key and creating intermediate maps as needed.
+func (d *decoder) setAnyKey(m map[string]interface{}, key unstable.Iterator, value *unstable.Node) error {
+ cur := m
+ for key.Next() {
+ name := d.intern(key.Node().Data)
+ if key.IsLast() {
+ av, err := d.decodeAny(value)
+ if err != nil {
+ return err
+ }
+ cur[name] = av
+ return nil
+ }
+ cur = d.anyChildTable(cur, name)
+ }
+ return nil
}
-/*
-Rules for the unmarshal code:
+// anyChildTable returns the child table at name within cur, creating it if
+// absent and descending into the current (last) element when an array table
+// occupies the slot. A non-container in the slot cannot occur for a document
+// the seen-tracker has accepted.
+func (d *decoder) anyChildTable(cur map[string]interface{}, name string) map[string]interface{} {
+ switch v := cur[name].(type) {
+ case map[string]interface{}:
+ return v
+ case []interface{}:
+ if len(v) > 0 {
+ if last, ok := v[len(v)-1].(map[string]interface{}); ok {
+ return last
+ }
+ }
+ }
+ nm := map[string]interface{}{}
+ cur[name] = nm
+ return nm
+}
-- The stack is used to keep track of which values need to be set where.
-- handle* functions <=> switch on a given unstable.Kind.
-- unmarshalX* functions need to unmarshal a node of kind X.
-- An "object" is either a struct or a map.
-*/
+// wrapError gives document context to errors generated while processing an
+// expression.
+func (d *decoder) wrapError(data []byte, err error) error {
+ var perr *unstable.ParserError
+ if errors.As(err, &perr) {
+ return wrapDecodeError(data, perr)
+ }
+ var mm *typeMismatchError
+ if errors.As(err, &mm) {
+ return wrapDecodeError(data, &unstable.ParserError{
+ Highlight: mm.highlight,
+ Message: mm.Error(),
+ Key: mm.key,
+ })
+ }
+ return err
+}
-func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) error {
- var x reflect.Value
- var err error
- var first bool // used for to clear array tables on first use
+// keyedError turns a bare error raised while processing an expression into a
+// ParserError carrying the position and key of that expression, so that it is
+// reported as a DecodeError with context. It is used for the errors returned
+// by SeenTracker.CheckExpression (redefinitions and duplicate keys, see issue
+// #668) and for table placement errors raised by walkTable (see issue #806).
+//
+// The highlight spans the expression's key. Unlike Node.Raw, key nodes always
+// carry a Raw range, so this works for tables and array tables too (whose own
+// Raw range is not set by the parser). For a duplicate detected inside an
+// inline table, node is the enclosing key-value expression, so the error
+// points at that expression's key.
+func (d *decoder) keyedError(node *unstable.Node, err error) error {
+ if err == nil {
+ return nil
+ }
- if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) {
- first, err = d.seen.CheckExpression(expr)
- if err != nil {
- return err
+ var key Key
+ var start, end unstable.Range
+ it := node.Key()
+ for it.Next() {
+ n := it.Node()
+ key = append(key, string(n.Data))
+ if len(key) == 1 {
+ start = n.Raw
}
+ end = n.Raw
+ }
+
+ var highlight []byte
+ if len(key) > 0 {
+ highlight = d.p.Raw(unstable.Range{
+ Offset: start.Offset,
+ Length: end.Offset + end.Length - start.Offset,
+ })
+ }
+
+ return &unstable.ParserError{
+ Highlight: highlight,
+ Message: strings.TrimPrefix(err.Error(), "toml: "),
+ Key: key,
+ }
+}
+
+func (d *decoder) handleRootExpression(expr *unstable.Node, root reflect.Value) error {
+ first, err := d.seen.CheckExpression(expr)
+ if err != nil {
+ return d.keyedError(expr, err)
}
switch expr.Kind {
@@ -285,1050 +676,1721 @@ func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) err
if d.skipUntilTable {
return nil
}
- x, err = d.handleKeyValue(expr, v)
+ if d.captureIdx >= 0 {
+ d.captureKeyValue(expr)
+ return nil
+ }
+ return d.handleKeyValueExpression(expr, root)
case unstable.Table:
+ d.flushTable()
d.skipUntilTable = false
+ d.captureIdx = -1
d.strict.EnterTable(expr)
- x, err = d.handleTable(expr.Key(), v)
+ return d.handleTableExpression(expr, root, false, first)
case unstable.ArrayTable:
+ d.flushTable()
d.skipUntilTable = false
- d.strict.EnterArrayTable(expr)
- d.clearArrayTable = first
- x, err = d.handleArrayTable(expr.Key(), v)
+ d.captureIdx = -1
+ d.strict.EnterTable(expr)
+ return d.handleTableExpression(expr, root, true, first)
default:
- panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind))
+ return unstable.NewParserError(expr.Data, "unsupported expression kind %s", expr.Kind)
+ }
+}
+
+// updateTableKey copies the parts of the key of a table expression into
+// tableKey.
+func (d *decoder) updateTableKey(expr *unstable.Node) {
+ d.tableKey = d.tableKey[:0]
+ it := expr.Key()
+ for it.Next() {
+ d.tableKey = append(d.tableKey, d.intern(it.Node().Data))
}
+}
- if d.skipUntilTable {
- if expr.Kind == unstable.Table || expr.Kind == unstable.ArrayTable {
- d.strict.MissingTable(expr)
+func (d *decoder) handleTableExpression(expr *unstable.Node, root reflect.Value, isArrayTable bool, first bool) error {
+ d.updateTableKey(expr)
+
+ // Check whether this table belongs to an exisiting raw capture (split
+ // tables, or children of a table assigned to an Unmarshaler).
+ if d.unmarshalerInterface {
+ if d.resumeCapture(expr) {
+ return nil
}
- } else if err == nil && x.IsValid() {
- v.Set(x)
}
- return err
+ // Reset the per-segment array indexes.
+ d.segIdx = d.segIdx[:0]
+ for i := 0; i <= len(d.tableKey); i++ {
+ d.segIdx = append(d.segIdx, -1)
+ }
+
+ return d.walkTable(root, expr, isArrayTable, first)
}
-func (d *decoder) handleArrayTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
- if key.Next() {
- return d.handleArrayTablePart(key, v)
+// newContainerElem returns a fresh element for a slice of the given element
+// type. Plain interface elements start out as an empty table.
+func newContainerElem(et reflect.Type) reflect.Value {
+ if et == interfaceType {
+ return reflect.ValueOf(map[string]interface{}{})
}
- return d.handleKeyValues(v)
+ return reflect.New(et).Elem()
}
-func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
- switch v.Kind() {
- case reflect.Interface:
- elem := v.Elem()
- if !elem.IsValid() {
- elem = reflect.New(sliceInterfaceType).Elem()
- elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
- } else if elem.Kind() == reflect.Slice {
- if elem.Type() != sliceInterfaceType {
- elem = reflect.New(sliceInterfaceType).Elem()
- elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
- } else if !elem.CanSet() {
- nelem := reflect.New(sliceInterfaceType).Elem()
- nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))
- reflect.Copy(nelem, elem)
- elem = nelem
+// walkTable processes a [table] or [[array table]] header: it creates the
+// intermediate containers, appends array-table elements, applies the strict
+// policy, registers unmarshaler-interface captures, and caches the target
+// container so that the key-values that follow are stored directly.
+//
+// Map values are not addressable: when one needs in-place mutations (struct
+// or array values), a copy is made and registered to be stored back when the
+// table changes (see flushTable). Maps and slices are references and are
+// traversed without copies.
+func (d *decoder) walkTable(root reflect.Value, expr *unstable.Node, isArrayTable bool, first bool) error {
+ v := root
+ pf := slotWriter{kind: 1, slot: root}
+ idx := 0
+
+walk:
+ for {
+ // Dereference pointers in place.
+ for v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ elem := v.Elem()
+ pf = slotWriter{kind: 1, slot: elem}
+ v = elem
+ }
+
+ // Tables assigned to a type implementing the unmarshaler interface
+ // are captured as raw bytes, delivered once the document is read.
+ if d.unmarshalerInterface && hasUnmarshaler(v) {
+ d.startCapture(idx, expr)
+ return nil
+ }
+
+ if idx >= len(d.tableKey) {
+ break walk
+ }
+
+ name := d.tableKey[idx]
+
+ switch v.Kind() {
+ case reflect.Interface:
+ if !v.IsNil() {
+ c := v.Elem()
+ if k := c.Kind(); k == reflect.Map || k == reflect.Slice {
+ // Reference types: mutations are visible through the
+ // existing interface value.
+ v = c
+ continue
+ }
+ }
+ // Anything else is replaced by a fresh generic map.
+ if !mapStringInterfaceType.AssignableTo(v.Type()) {
+ return d.keyedError(expr, fmt.Errorf("cannot store a table in a %s", v.Type()))
+ }
+ fresh := reflect.ValueOf(map[string]interface{}{})
+ d.storeSlot(&pf, fresh)
+ v = fresh
+ case reflect.Slice:
+ if v.Len() == 0 {
+ // Implicit creation of the first element: the array table
+ // that would create it has not been seen yet (issue 995).
+ if v.IsNil() {
+ v = reflect.MakeSlice(v.Type(), 0, 4)
+ }
+ v = reflect.Append(v, newContainerElem(v.Type().Elem()))
+ d.storeSlot(&pf, v)
+ }
+ n := v.Len() - 1
+ d.segIdx[idx] = n
+ elem := v.Index(n)
+ pf = slotWriter{kind: 1, slot: elem}
+ v = elem
+ case reflect.Array:
+ key := d.joinPath(d.tableKey[:idx])
+ cnt := d.arrayCount(key)
+ if cnt == 0 {
+ cnt = 1
+ d.setArrayCount(key, 1)
+ }
+ if cnt > v.Len() {
+ return d.keyedError(expr, fmt.Errorf("cannot reach element %d of array of size %d", cnt-1, v.Len()))
}
- if d.clearArrayTable && elem.Len() > 0 {
- elem.SetLen(0)
- d.clearArrayTable = false
+ d.segIdx[idx] = cnt - 1
+ elem := v.Index(cnt - 1)
+ pf = slotWriter{kind: 1, slot: elem}
+ v = elem
+ case reflect.Map:
+ if v.IsNil() {
+ nm := reflect.MakeMap(v.Type())
+ d.storeSlot(&pf, nm)
+ v = nm
+ }
+ var key reflect.Value
+ var w slotWriter
+ if v.Type().Key() == stringType {
+ key = d.stringMapKey(name)
+ w = slotWriter{kind: 3, m: v, ks: name}
+ } else {
+ k, err := makeMapKey(v.Type().Key(), name)
+ if err != nil {
+ return err
+ }
+ key = k
+ w = slotWriter{kind: 2, m: v, k: k}
+ }
+
+ elem := v.MapIndex(key)
+
+ // The last part of an array table is finalized as a slice
+ // container: do not materialize a table for it.
+ if isArrayTable && idx == len(d.tableKey)-1 {
+ et := v.Type().Elem()
+ switch et.Kind() {
+ case reflect.Interface, reflect.Slice, reflect.Array:
+ if elem.IsValid() {
+ v = elem
+ } else {
+ v = reflect.Zero(et)
+ }
+ pf = w
+ idx++
+ continue
+ default:
+ }
+ }
+
+ if elem.IsValid() {
+ ce := elem
+ ceIface := false
+ if ce.Kind() == reflect.Interface {
+ ceIface = true
+ if !ce.IsNil() {
+ ce = ce.Elem()
+ }
+ }
+ switch ce.Kind() {
+ case reflect.Map, reflect.Slice:
+ pf = w
+ v = ce
+ case reflect.Ptr:
+ if ce.IsNil() {
+ np := reflect.New(ce.Type().Elem())
+ d.storeSlot(&w, np)
+ ce = np
+ }
+ pf = w
+ v = ce
+ case reflect.Struct, reflect.Array:
+ if ceIface {
+ // Interface-held non-generic content is replaced.
+ fresh := reflect.ValueOf(map[string]interface{}{})
+ d.storeSlot(&w, fresh)
+ pf = w
+ v = fresh
+ } else {
+ tmp := reflect.New(elem.Type()).Elem()
+ tmp.Set(elem)
+ d.tableFlush = append(d.tableFlush, flushOp{w: w, val: tmp})
+ pf = slotWriter{kind: 1, slot: tmp}
+ v = tmp
+ }
+ default:
+ if !ceIface {
+ return d.keyedError(expr, fmt.Errorf("cannot store a table in a %s", ce.Type()))
+ }
+ fresh := reflect.ValueOf(map[string]interface{}{})
+ d.storeSlot(&w, fresh)
+ pf = w
+ v = fresh
+ }
+ } else {
+ et := v.Type().Elem()
+ switch et.Kind() {
+ case reflect.Interface:
+ if !mapStringInterfaceType.AssignableTo(et) {
+ return d.keyedError(expr, fmt.Errorf("cannot store a table in a %s", et))
+ }
+ fresh := reflect.ValueOf(map[string]interface{}{})
+ d.storeSlot(&w, fresh)
+ pf = w
+ v = fresh
+ case reflect.Map:
+ nm := reflect.MakeMap(et)
+ d.storeSlot(&w, nm)
+ pf = w
+ v = nm
+ case reflect.Ptr:
+ np := reflect.New(et.Elem())
+ d.storeSlot(&w, np)
+ pf = w
+ v = np
+ case reflect.Struct, reflect.Array, reflect.Slice:
+ tmp := reflect.New(et).Elem()
+ d.tableFlush = append(d.tableFlush, flushOp{w: w, val: tmp})
+ pf = slotWriter{kind: 1, slot: tmp}
+ v = tmp
+ default:
+ return d.keyedError(expr, fmt.Errorf("cannot store a table in a %s", et))
+ }
}
+ idx++
+ case reflect.Struct:
+ plan := planForType(v.Type())
+ f, found := plan.lookup(name)
+ if !found {
+ d.strict.MissingTable(expr)
+ d.skipUntilTable = true
+ return nil
+ }
+ fv, err := fieldByIndexAlloc(v, f.index)
+ if err != nil {
+ return err
+ }
+ pf = slotWriter{kind: 1, slot: fv}
+ v = fv
+ idx++
+ default:
+ return d.keyedError(expr, fmt.Errorf("cannot store a table in a %s", v.Kind()))
}
- return d.handleArrayTableCollectionLast(key, elem)
- case reflect.Ptr:
- elem := v.Elem()
- if !elem.IsValid() {
- ptr := reflect.New(v.Type().Elem())
- v.Set(ptr)
- elem = ptr.Elem()
+ }
+
+ if isArrayTable {
+ akey := d.joinPath(d.tableKey)
+ d.resetChildArrayCounts(akey)
+
+ // Unwrap an interface container.
+ if v.Kind() == reflect.Interface {
+ var slice []interface{}
+ if !v.IsNil() {
+ if s, ok := v.Elem().Interface().([]interface{}); ok {
+ slice = s
+ }
+ }
+ if first {
+ slice = slice[:0]
+ }
+ m := map[string]interface{}{}
+ slice = append(slice, m)
+ sv := reflect.ValueOf(slice)
+ d.storeSlot(&pf, sv)
+ d.setArrayCount(akey, len(slice))
+ d.segIdx[len(d.tableKey)] = len(slice) - 1
+ d.tableTarget = reflect.ValueOf(m)
+ d.tableParentSlot = slotWriter{kind: 1, slot: sv.Index(len(slice) - 1)}
+ d.tableTargetValid = true
+ return nil
}
- elem, err := d.handleArrayTableCollectionLast(key, elem)
- if err != nil {
- return reflect.Value{}, err
+ switch v.Kind() {
+ case reflect.Slice:
+ if v.IsNil() {
+ v = reflect.MakeSlice(v.Type(), 0, 4)
+ } else if first {
+ v = v.Slice(0, 0)
+ }
+ v = reflect.Append(v, newContainerElem(v.Type().Elem()))
+ d.storeSlot(&pf, v)
+ n := v.Len() - 1
+ d.setArrayCount(akey, n+1)
+ d.segIdx[len(d.tableKey)] = n
+ elem := v.Index(n)
+ if d.unmarshalerInterface && hasUnmarshaler(elem) {
+ d.startCapture(len(d.tableKey), expr)
+ return nil
+ }
+ pf = slotWriter{kind: 1, slot: elem}
+ v = elem
+ case reflect.Array:
+ cnt := d.arrayCount(akey)
+ if first {
+ cnt = 0
+ }
+ if cnt >= v.Len() {
+ return d.keyedError(expr, fmt.Errorf("array of size %d is too small to store this array table", v.Len()))
+ }
+ v.Index(cnt).Set(reflect.Zero(v.Type().Elem()))
+ d.setArrayCount(akey, cnt+1)
+ d.segIdx[len(d.tableKey)] = cnt
+ elem := v.Index(cnt)
+ if d.unmarshalerInterface && hasUnmarshaler(elem) {
+ d.startCapture(len(d.tableKey), expr)
+ return nil
+ }
+ pf = slotWriter{kind: 1, slot: elem}
+ v = elem
+ default:
+ return d.keyedError(expr, fmt.Errorf("cannot store an array table in a %s", v.Kind()))
+ }
+ }
+
+ // Settle on the concrete container for the key-values that follow.
+ for {
+ switch v.Kind() {
+ case reflect.Ptr:
+ if v.IsNil() {
+ if !v.CanSet() {
+ return nil
+ }
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ elem := v.Elem()
+ pf = slotWriter{kind: 1, slot: elem}
+ v = elem
+ continue
+ case reflect.Interface:
+ if !v.IsNil() {
+ c := v.Elem()
+ if c.Type() == mapStringInterfaceType || c.Type() == sliceInterfaceType {
+ v = c
+ continue
+ }
+ }
+ if !mapStringInterfaceType.AssignableTo(v.Type()) {
+ return d.keyedError(expr, fmt.Errorf("cannot store a table in a %s", v.Type()))
+ }
+ fresh := reflect.ValueOf(map[string]interface{}{})
+ d.storeSlot(&pf, fresh)
+ v = fresh
+ continue
+ case reflect.Slice:
+ if v.Len() == 0 {
+ if v.IsNil() {
+ v = reflect.MakeSlice(v.Type(), 0, 4)
+ }
+ v = reflect.Append(v, newContainerElem(v.Type().Elem()))
+ d.storeSlot(&pf, v)
+ }
+ n := v.Len() - 1
+ d.segIdx[len(d.tableKey)] = n
+ elem := v.Index(n)
+ pf = slotWriter{kind: 1, slot: elem}
+ v = elem
+ continue
+ case reflect.Map, reflect.Struct:
+ d.tableTarget = v
+ d.tableParentSlot = pf
+ d.tableTargetValid = true
+ return nil
+ default:
+ return d.keyedError(expr, fmt.Errorf("cannot store a table in a %s", v.Kind()))
}
- v.Elem().Set(elem)
+ }
+}
- return v, nil
- case reflect.Slice:
- if d.clearArrayTable && v.Len() > 0 {
- v.SetLen(0)
- d.clearArrayTable = false
+// resumeCapture looks for an existing capture this table expression belongs
+// to. It returns true if the expression was consumed.
+func (d *decoder) resumeCapture(expr *unstable.Node) bool {
+ // Iterate in reverse, so that tables attach to the latest element of
+ // array tables.
+ for i := len(d.captures) - 1; i >= 0; i-- {
+ c := &d.captures[i]
+ if len(d.tableKey) < len(c.names) {
+ continue
}
- elemType := v.Type().Elem()
- var elem reflect.Value
- if elemType.Kind() == reflect.Interface {
- elem = makeMapStringInterface()
- } else {
- elem = reflect.New(elemType).Elem()
+ if expr.Kind == unstable.ArrayTable && len(d.tableKey) == len(c.names) {
+ // A new element of an array table is not part of the capture of
+ // the previous element.
+ continue
}
- elem2, err := d.handleArrayTable(key, elem)
- if err != nil {
- return reflect.Value{}, err
+ match := true
+ for j, p := range c.names {
+ if d.tableKey[j] != p {
+ match = false
+ break
+ }
}
- if elem2.IsValid() {
- elem = elem2
+ if !match {
+ continue
}
- return reflect.Append(v, elem), nil
- case reflect.Array:
- idx := d.arrayIndex(true, v)
- if idx >= v.Len() {
- return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)
+ d.captureIdx = i
+ if len(d.tableKey) > len(c.names) {
+ d.appendCaptureHeader(c, expr, len(c.names))
}
- elem := v.Index(idx)
- _, err := d.handleArrayTable(key, elem)
- return v, err
- default:
- return reflect.Value{}, d.typeMismatchError("array table", v.Type())
+ return true
}
+ return false
}
-// When parsing an array table expression, each part of the key needs to be
-// evaluated like a normal key, but if it returns a collection, it also needs to
-// point to the last element of the collection. Unless it is the last part of
-// the key, then it needs to create a new element at the end.
-func (d *decoder) handleArrayTableCollection(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
- if key.IsLast() {
- return d.handleArrayTableCollectionLast(key, v)
+// appendCaptureHeader writes the table header of expr in the capture buffer,
+// adjusted to be relative to the capture root.
+func (d *decoder) appendCaptureHeader(c *rawCapture, expr *unstable.Node, skip int) {
+ c.buf = append(c.buf, '[')
+ if expr.Kind == unstable.ArrayTable {
+ c.buf = append(c.buf, '[')
}
+ c.buf = append(c.buf, d.rawKeySuffix(expr, skip)...)
+ c.buf = append(c.buf, ']')
+ if expr.Kind == unstable.ArrayTable {
+ c.buf = append(c.buf, ']')
+ }
+ c.buf = append(c.buf, '\n')
+}
- switch v.Kind() {
- case reflect.Ptr:
- elem := v.Elem()
- if !elem.IsValid() {
- ptr := reflect.New(v.Type().Elem())
- v.Set(ptr)
- elem = ptr.Elem()
+// rawKeySuffix returns the raw bytes of the key of the expression, skipping
+// the first n parts.
+func (d *decoder) rawKeySuffix(expr *unstable.Node, n int) []byte {
+ it := expr.Key()
+ idx := 0
+ var start, end unstable.Range
+ for it.Next() {
+ if idx >= n {
+ r := it.Node().Raw
+ if start.Length == 0 && start.Offset == 0 && idx == n {
+ start = r
+ }
+ end = r
}
+ idx++
+ }
+ return d.p.Data()[start.Offset : end.Offset+end.Length]
+}
- elem, err := d.handleArrayTableCollection(key, elem)
+// startCapture registers a new capture for the table at the given path
+// (prefix of tableKey).
+func (d *decoder) startCapture(pathLen int, expr *unstable.Node) {
+ names := make([]string, pathLen)
+ copy(names, d.tableKey[:pathLen])
+ indexes := make([]int, pathLen+1)
+ copy(indexes, d.segIdx[:pathLen+1])
+ d.captures = append(d.captures, rawCapture{
+ names: names,
+ indexes: indexes,
+ })
+ d.captureIdx = len(d.captures) - 1
+ if pathLen < len(d.tableKey) {
+ d.appendCaptureHeader(&d.captures[d.captureIdx], expr, pathLen)
+ }
+}
+
+// startRootCapture opens a capture covering the entire document, used when the
+// root target itself implements the Unmarshaler interface. It is opened before
+// reading any expression: top-level key-values are then accumulated through the
+// regular capture branch, and its empty name path matches every table in
+// resumeCapture, so the whole document is handed to UnmarshalTOML once. The
+// single index slot is -1 because the root is never reached through an array
+// table.
+func (d *decoder) startRootCapture() {
+ d.captures = append(d.captures, rawCapture{indexes: []int{-1}})
+ d.captureIdx = len(d.captures) - 1
+}
+
+// resolveCapture walks back to the target of a capture and delivers the
+// accumulated raw bytes to its UnmarshalTOML implementation.
+func (d *decoder) resolveCapture(v reflect.Value, c *rawCapture, idx int, indexed bool) (reflect.Value, error) {
+ if v.Kind() == reflect.Ptr {
+ if v.Type().Implements(unmarshalerType) && idx == len(c.names) {
+ u, _ := unmarshalerOf(v)
+ return v, u.UnmarshalTOML(c.buf)
+ }
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ nv, err := d.resolveCapture(v.Elem(), c, idx, indexed)
if err != nil {
return reflect.Value{}, err
}
- if elem.IsValid() {
- v.Elem().Set(elem)
+ if nv.IsValid() {
+ v.Elem().Set(nv)
}
-
return v, nil
- case reflect.Slice:
- elem := v.Index(v.Len() - 1)
- x, err := d.handleArrayTable(key, elem)
- if err != nil || d.skipUntilTable {
+ }
+
+ if !indexed && (v.Kind() == reflect.Slice || v.Kind() == reflect.Array) && c.indexes[idx] >= 0 {
+ i := c.indexes[idx]
+ if i >= v.Len() {
+ return reflect.Value{}, errors.New("toml: internal error: capture index out of range")
+ }
+ elem := v.Index(i)
+ nv, err := d.resolveCapture(elem, c, idx, true)
+ if err != nil {
return reflect.Value{}, err
}
- if x.IsValid() {
- elem.Set(x)
+ if nv.IsValid() {
+ elem.Set(nv)
}
+ return v, nil
+ }
- return v, err
- case reflect.Array:
- idx := d.arrayIndex(false, v)
- if idx >= v.Len() {
- return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)
+ if idx == len(c.names) {
+ u, ok := unmarshalerOf(v)
+ if !ok {
+ return reflect.Value{}, errors.New("toml: internal error: capture target does not implement UnmarshalTOML")
}
- elem := v.Index(idx)
- _, err := d.handleArrayTable(key, elem)
- return v, err
+ return v, u.UnmarshalTOML(c.buf)
}
- return d.handleArrayTable(key, v)
-}
+ name := c.names[idx]
-func (d *decoder) handleKeyPart(key unstable.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
- var rv reflect.Value
-
- // First, dispatch over v to make sure it is a valid object.
- // There is no guarantee over what it could be.
switch v.Kind() {
- case reflect.Ptr:
- elem := v.Elem()
- if !elem.IsValid() {
- v.Set(reflect.New(v.Type().Elem()))
+ case reflect.Struct:
+ plan := planForType(v.Type())
+ f, found := plan.lookup(name)
+ if !found {
+ return v, nil
}
- elem = v.Elem()
- return d.handleKeyPart(key, elem, nextFn, makeFn)
- case reflect.Map:
- vt := v.Type()
-
- // Create the key for the map element. Convert to key type.
- mk, err := d.keyFromData(vt.Key(), key.Node().Data)
+ fv, err := fieldByIndexAlloc(v, f.index)
if err != nil {
return reflect.Value{}, err
}
-
- // If the map does not exist, create it.
- if v.IsNil() {
- vt := v.Type()
- v = reflect.MakeMap(vt)
- rv = v
- }
-
- mv := v.MapIndex(mk)
- set := false
- if !mv.IsValid() {
- // If there is no value in the map, create a new one according to
- // the map type. If the element type is interface, create either a
- // map[string]interface{} or a []interface{} depending on whether
- // this is the last part of the array table key.
-
- t := vt.Elem()
- if t.Kind() == reflect.Interface {
- mv = makeFn()
- } else {
- mv = reflect.New(t).Elem()
- }
- set = true
- } else if mv.Kind() == reflect.Interface {
- mv = mv.Elem()
- if !mv.IsValid() {
- mv = makeFn()
- }
- set = true
- } else if !mv.CanAddr() {
- vt := v.Type()
- t := vt.Elem()
- oldmv := mv
- mv = reflect.New(t).Elem()
- mv.Set(oldmv)
- set = true
- }
-
- x, err := nextFn(key, mv)
+ nv, err := d.resolveCapture(fv, c, idx+1, false)
if err != nil {
return reflect.Value{}, err
}
-
- if x.IsValid() {
- mv = x
- set = true
+ if nv.IsValid() && fv.CanSet() {
+ fv.Set(nv)
}
-
- if set {
- v.SetMapIndex(mk, mv)
+ return v, nil
+ case reflect.Map:
+ key, err := makeMapKey(v.Type().Key(), name)
+ if err != nil {
+ return reflect.Value{}, err
}
- case reflect.Struct:
- path, found := structFieldPath(v, string(key.Node().Data))
- if !found {
- d.skipUntilTable = true
- return reflect.Value{}, nil
+ if v.IsNil() {
+ v = reflect.MakeMap(v.Type())
}
-
- if d.errorContext == nil {
- d.errorContext = new(errorContext)
+ elem := reflect.New(v.Type().Elem()).Elem()
+ if existing := v.MapIndex(key); existing.IsValid() {
+ elem.Set(existing)
}
- t := v.Type()
- d.errorContext.Struct = t
- d.errorContext.Field = path
-
- f := fieldByIndex(v, path)
- x, err := nextFn(key, f)
- if err != nil || d.skipUntilTable {
+ nv, err := d.resolveCapture(elem, c, idx+1, false)
+ if err != nil {
return reflect.Value{}, err
}
- if x.IsValid() {
- f.Set(x)
+ if nv.IsValid() {
+ v.SetMapIndex(key, nv)
}
- d.errorContext.Field = nil
- d.errorContext.Struct = nil
+ return v, nil
case reflect.Interface:
- if v.Elem().IsValid() {
- v = v.Elem()
- } else {
- v = makeMapStringInterface()
- }
-
- x, err := d.handleKeyPart(key, v, nextFn, makeFn)
- if err != nil {
+ elem := elemOrNewMap(v)
+ nv, err := d.resolveCapture(elem, c, idx, indexed)
+ if err != nil || !nv.IsValid() {
return reflect.Value{}, err
}
- if x.IsValid() {
- v = x
- }
- rv = v
+ return nv, nil
default:
- panic(fmt.Errorf("unhandled part: %s", v.Kind()))
+ return reflect.Value{}, fmt.Errorf("toml: internal error: cannot resolve capture target through %s", v.Kind())
}
+}
- return rv, nil
+// captureKeyValue appends the raw bytes of a key-value expression to the
+// current capture.
+func (d *decoder) captureKeyValue(expr *unstable.Node) {
+ c := &d.captures[d.captureIdx]
+ c.buf = append(c.buf, d.p.Raw(expr.Raw)...)
+ c.buf = append(c.buf, '\n')
}
-// HandleArrayTablePart navigates the Go structure v using the key v. It is
-// only used for the prefix (non-last) parts of an array-table. When
-// encountering a collection, it should go to the last element.
-func (d *decoder) handleArrayTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
- var makeFn valueMakerFn
- if key.IsLast() {
- makeFn = makeSliceInterface
- } else {
- makeFn = makeMapStringInterface
- }
- return d.handleKeyPart(key, v, d.handleArrayTableCollection, makeFn)
+// hasUnmarshaler reports whether v can provide an unstable.Unmarshaler,
+// without allocating anything.
+func hasUnmarshaler(v reflect.Value) bool {
+ t := v.Type()
+ return t.Implements(unmarshalerType) || (v.CanAddr() && reflect.PtrTo(t).Implements(unmarshalerType))
}
-// HandleTable returns a reference when it has checked the next expression but
-// cannot handle it.
-func (d *decoder) handleTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
- if v.Kind() == reflect.Slice {
- if v.Len() == 0 {
- return reflect.Value{}, unstable.NewParserError(key.Node().Data, "cannot store a table in a slice")
- }
- elem := v.Index(v.Len() - 1)
- x, err := d.handleTable(key, elem)
+// makeMapKey converts a TOML key into a value usable as the given map key
+// type.
+func makeMapKey(kt reflect.Type, name string) (reflect.Value, error) {
+ switch kt.Kind() {
+ case reflect.String:
+ return reflect.ValueOf(name).Convert(kt), nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ i, err := strconv.ParseInt(name, 10, 64)
if err != nil {
- return reflect.Value{}, err
+ return reflect.Value{}, fmt.Errorf("toml: cannot parse map key %q as %s: %w", name, kt, err)
}
- if x.IsValid() {
- elem.Set(x)
- }
- return reflect.Value{}, nil
- }
- if key.Next() {
- // Still scoping the key
- return d.handleTablePart(key, v)
- }
- // Done scoping the key.
- // Now handle all the key-value expressions in this table.
- return d.handleKeyValues(v)
-}
-
-// Handle root expressions until the end of the document or the next
-// non-key-value.
-func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
- var rv reflect.Value
- for d.nextExpr() {
- expr := d.expr()
- if expr.Kind != unstable.KeyValue {
- // Stash the expression so that fromParser can just loop and use
- // the right handler.
- // We could just recurse ourselves here, but at least this gives a
- // chance to pop the stack a bit.
- d.stashExpr()
- break
+ k := reflect.New(kt).Elem()
+ if k.OverflowInt(i) {
+ return reflect.Value{}, fmt.Errorf("toml: map key %q overflows %s", name, kt)
}
-
- _, err := d.seen.CheckExpression(expr)
+ k.SetInt(i)
+ return k, nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ u, err := strconv.ParseUint(name, 10, 64)
if err != nil {
- return reflect.Value{}, err
+ return reflect.Value{}, fmt.Errorf("toml: cannot parse map key %q as %s: %w", name, kt, err)
}
-
- x, err := d.handleKeyValue(expr, v)
+ k := reflect.New(kt).Elem()
+ if k.OverflowUint(u) {
+ return reflect.Value{}, fmt.Errorf("toml: map key %q overflows %s", name, kt)
+ }
+ k.SetUint(u)
+ return k, nil
+ case reflect.Float32, reflect.Float64:
+ f, err := strconv.ParseFloat(name, 64)
if err != nil {
- return reflect.Value{}, err
+ return reflect.Value{}, fmt.Errorf("toml: cannot parse map key %q as %s: %w", name, kt, err)
+ }
+ k := reflect.New(kt).Elem()
+ k.SetFloat(f)
+ return k, nil
+ case reflect.Ptr:
+ if kt.Implements(textUnmarshalerType) {
+ k := reflect.New(kt.Elem())
+ err := k.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(name))
+ if err != nil {
+ return reflect.Value{}, fmt.Errorf("toml: error unmarshaling map key %q: %w", name, err)
+ }
+ return k, nil
}
- if x.IsValid() {
- v = x
- rv = x
+ default:
+ if reflect.PtrTo(kt).Implements(textUnmarshalerType) {
+ k := reflect.New(kt)
+ err := k.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(name))
+ if err != nil {
+ return reflect.Value{}, fmt.Errorf("toml: error unmarshaling map key %q: %w", name, err)
+ }
+ return k.Elem(), nil
}
}
- return rv, nil
+ return reflect.Value{}, fmt.Errorf("toml: cannot decode a key into a map with key type %s", kt)
}
-type (
- handlerFn func(key unstable.Iterator, v reflect.Value) (reflect.Value, error)
- valueMakerFn func() reflect.Value
-)
-
-func makeMapStringInterface() reflect.Value {
- return reflect.MakeMap(mapStringInterfaceType)
+// elemOrNewMap unwraps an interface value to descend into it. Contents that
+// can hold a table (generic maps and slices) are kept; anything else is
+// replaced by a fresh map[string]interface{}. Maps and slices are reference
+// types: they are returned directly, not copied.
+func elemOrNewMap(v reflect.Value) reflect.Value {
+ if !v.IsNil() {
+ concrete := v.Elem()
+ t := concrete.Type()
+ if t == mapStringInterfaceType || t == sliceInterfaceType {
+ return concrete
+ }
+ }
+ return reflect.ValueOf(map[string]interface{}{})
}
-func makeSliceInterface() reflect.Value {
- return reflect.MakeSlice(sliceInterfaceType, 0, 16)
-}
+// handleKeyValueExpression stores the value of a top-level key-value
+// expression, relative to the current table.
+func (d *decoder) handleKeyValueExpression(expr *unstable.Node, root reflect.Value) error {
+ d.path = d.path[:0]
-func (d *decoder) handleTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
- return d.handleKeyPart(key, v, d.handleTable, makeMapStringInterface)
-}
+ target := root
+ useCache := d.tableTargetValid && len(d.tableKey) > 0
+ if useCache {
+ target = d.tableTarget
+ } else {
+ for _, name := range d.tableKey {
+ d.path = append(d.path, pathPart{name: name})
+ }
+ }
-func (d *decoder) tryTextUnmarshaler(node *unstable.Node, v reflect.Value) (bool, error) {
- // Special case for time, because we allow to unmarshal to it from
- // different kind of AST nodes.
- if v.Type() == timeType {
- return false, nil
+ it := expr.Key()
+ for it.Next() {
+ d.path = append(d.path, pathPart{node: it.Node()})
}
- if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {
- err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)
- if err != nil {
- return false, unstable.NewParserError(d.p.Raw(node.Raw), "%w", err)
+ nv, err := d.descend(target, d.path, 0, expr, expr.Value())
+ if err != nil {
+ return d.contextualizeError(err, useCache)
+ }
+ if !nv.IsValid() {
+ return nil
+ }
+ if useCache {
+ // The target may have been replaced (e.g. a nil map allocated):
+ // re-link it into its parent.
+ if nv.Kind() == reflect.Map && nv.Pointer() != d.tableTarget.Pointer() {
+ d.storeSlot(&d.tableParentSlot, nv)
+ d.tableTarget = nv
+ }
+ } else {
+ if root.CanSet() {
+ root.Set(nv)
}
-
- return true, nil
}
-
- return false, nil
+ return nil
}
-func (d *decoder) handleValue(value *unstable.Node, v reflect.Value) error {
- for v.Kind() == reflect.Ptr {
- v = initAndDereferencePointer(v)
+// descend walks the given key path into v, and assigns the value at the
+// end. It returns the value to store back at this level. An invalid value
+// means nothing should be stored (e.g. unknown field).
+func (d *decoder) descend(v reflect.Value, path []pathPart, idx int, expr *unstable.Node, value *unstable.Node) (reflect.Value, error) {
+ if idx == len(path) {
+ return d.assignValue(v, expr, value)
}
- if d.unmarshalerInterface {
- if v.CanAddr() && v.Addr().CanInterface() {
- if outi, ok := v.Addr().Interface().(unstable.Unmarshaler); ok {
- return outi.UnmarshalTOML(value)
- }
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ nv, err := d.descend(v.Elem(), path, idx, expr, value)
+ if err != nil || !nv.IsValid() {
+ return reflect.Value{}, err
}
+ v.Elem().Set(nv)
+ return v, nil
}
- ok, err := d.tryTextUnmarshaler(value, v)
- if ok || err != nil {
- return err
+ // A target implementing the unmarshaler interface consumes the value,
+ // whatever the remaining parts of the key are.
+ if d.unmarshalerInterface {
+ if u, ok := unmarshalerOf(v); ok {
+ return v, u.UnmarshalTOML(d.rawValue(expr, value))
+ }
}
- switch value.Kind {
- case unstable.String:
- return d.unmarshalString(value, v)
- case unstable.Integer:
- return d.unmarshalInteger(value, v)
- case unstable.Float:
- return d.unmarshalFloat(value, v)
- case unstable.Bool:
- return d.unmarshalBool(value, v)
- case unstable.DateTime:
- return d.unmarshalDateTime(value, v)
- case unstable.LocalDate:
- return d.unmarshalLocalDate(value, v)
- case unstable.LocalTime:
- return d.unmarshalLocalTime(value, v)
- case unstable.LocalDateTime:
- return d.unmarshalLocalDateTime(value, v)
- case unstable.InlineTable:
- return d.unmarshalInlineTable(value, v)
- case unstable.Array:
- return d.unmarshalArray(value, v)
- default:
- panic(fmt.Errorf("handleValue not implemented for %s", value.Kind))
- }
-}
+ part := path[idx]
-func (d *decoder) unmarshalArray(array *unstable.Node, v reflect.Value) error {
switch v.Kind() {
- case reflect.Slice:
- if v.IsNil() {
- v.Set(reflect.MakeSlice(v.Type(), 0, 16))
+ case reflect.Map:
+ // Native fast path for the most common generic target: walk the
+ // remaining dotted-key path with plain Go map operations and decode
+ // the value directly, skipping the reflect.Value round-trips
+ // (stringMapKey, MapIndex, New, SetMapIndex) entirely.
+ if !d.unmarshalerInterface && v.Type() == mapStringInterfaceType {
+ return d.descendStrMap(v, path, idx, value)
+ }
+ var name string
+ var key reflect.Value
+ var err error
+ fastKey := v.Type().Key() == stringType
+ if fastKey {
+ name = d.partString(&part)
+ key = d.stringMapKey(name)
} else {
- v.SetLen(0)
- }
- case reflect.Array:
- // arrays are always initialized
- case reflect.Interface:
- elem := v.Elem()
- if !elem.IsValid() {
- elem = reflect.New(sliceInterfaceType).Elem()
- elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
- } else if elem.Kind() == reflect.Slice {
- if elem.Type() != sliceInterfaceType {
- elem = reflect.New(sliceInterfaceType).Elem()
- elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
- } else if !elem.CanSet() {
- nelem := reflect.New(sliceInterfaceType).Elem()
- nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))
- reflect.Copy(nelem, elem)
- elem = nelem
+ key, err = makeMapKey(v.Type().Key(), d.partString(&part))
+ if err != nil {
+ return reflect.Value{}, err
}
}
- err := d.unmarshalArray(array, elem)
+ if v.IsNil() {
+ v = reflect.MakeMap(v.Type())
+ }
+ elemType := v.Type().Elem()
+ existing := v.MapIndex(key)
+ var elem reflect.Value
+ switch {
+ case existing.IsValid():
+ elem = reflect.New(elemType).Elem()
+ elem.Set(existing)
+ case idx+1 == len(path) && elemType.Kind() == reflect.Interface:
+ // Fast path: a fresh interface element does not need to be
+ // materialized, the assigned value is stored directly.
+ elem = reflect.Zero(elemType)
+ default:
+ elem = reflect.New(elemType).Elem()
+ }
+ nv, err := d.descend(elem, path, idx+1, expr, value)
if err != nil {
- return err
+ return reflect.Value{}, err
}
- v.Set(elem)
- return nil
- default:
- // TODO: use newDecodeError, but first the parser needs to fill
- // array.Data.
- return d.typeMismatchError("array", v.Type())
- }
-
- elemType := v.Type().Elem()
-
- it := array.Children()
- idx := 0
- for it.Next() {
- n := it.Node()
-
- // TODO: optimize
- if v.Kind() == reflect.Slice {
- elem := reflect.New(elemType).Elem()
-
- err := d.handleValue(n, elem)
- if err != nil {
- return err
+ if nv.IsValid() {
+ if fastKey {
+ // The recursion may have overwritten the key buffer.
+ key = d.stringMapKey(name)
}
-
- v.Set(reflect.Append(v, elem))
- } else { // array
- if idx >= v.Len() {
- return nil
+ v.SetMapIndex(key, nv)
+ }
+ return v, nil
+ case reflect.Struct:
+ plan := planForType(v.Type())
+ f, found := plan.lookupBytes(part.bytes())
+ if !found {
+ if part.node != nil {
+ d.strict.MissingField(expr)
}
- elem := v.Index(idx)
- err := d.handleValue(n, elem)
- if err != nil {
- return err
+ return v, nil
+ }
+ fv, err := fieldByIndexAlloc(v, f.index)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ var nv reflect.Value
+ if idx+1 == len(path) {
+ // Leaf field: assign directly. descend's first action for a
+ // fully-consumed path is exactly this call, so skipping the extra
+ // frame is equivalent and avoids a call per scalar field.
+ nv, err = d.assignValue(fv, expr, value)
+ } else {
+ nv, err = d.descend(fv, path, idx+1, expr, value)
+ }
+ if err != nil {
+ var mm *typeMismatchError
+ if errors.As(err, &mm) {
+ err = &unstable.ParserError{
+ Highlight: mm.highlight,
+ Message: fmt.Sprintf("cannot decode TOML %s into struct field %s.%s of type %s",
+ mm.toml, v.Type(), f.fieldName, mm.target),
+ }
}
- idx++
+ return reflect.Value{}, err
}
- }
-
- return nil
-}
-
-func (d *decoder) unmarshalInlineTable(itable *unstable.Node, v reflect.Value) error {
- // Make sure v is an initialized object.
- switch v.Kind() {
- case reflect.Map:
- if v.IsNil() {
- v.Set(reflect.MakeMap(v.Type()))
+ if nv.IsValid() && fv.CanSet() {
+ fv.Set(nv)
}
- case reflect.Struct:
- // structs are always initialized.
+ return v, nil
case reflect.Interface:
- elem := v.Elem()
- if !elem.IsValid() {
- elem = makeMapStringInterface()
- v.Set(elem)
+ elem := elemOrNewMap(v)
+ nv, err := d.descend(elem, path, idx, expr, value)
+ if err != nil || !nv.IsValid() {
+ return reflect.Value{}, err
}
- return d.unmarshalInlineTable(itable, elem)
- default:
- return unstable.NewParserError(d.p.Raw(itable.Raw), "cannot store inline table in Go type %s", v.Kind())
- }
-
- it := itable.Children()
- for it.Next() {
- n := it.Node()
-
- x, err := d.handleKeyValue(n, v)
+ return nv, nil
+ case reflect.Slice:
+ if v.Len() == 0 {
+ if v.IsNil() {
+ v = reflect.MakeSlice(v.Type(), 0, 4)
+ }
+ v = reflect.Append(v, reflect.New(v.Type().Elem()).Elem())
+ }
+ elem := v.Index(v.Len() - 1)
+ nv, err := d.descend(elem, path, idx, expr, value)
if err != nil {
- return err
+ return reflect.Value{}, err
+ }
+ if nv.IsValid() {
+ elem.Set(nv)
+ }
+ return v, nil
+ case reflect.Array:
+ names := make([]string, idx)
+ for i := range names {
+ names[i] = path[i].str()
+ }
+ cnt := d.arrayCount(d.joinPath(names))
+ if cnt == 0 {
+ cnt = 1
}
- if x.IsValid() {
- v = x
+ elemIdx := cnt - 1
+ if elemIdx >= v.Len() {
+ return reflect.Value{}, unstable.NewParserError(keyHighlight(d.p.Data(), part.node),
+ "cannot reach element %d of array of size %d", elemIdx, v.Len())
}
+ elem := v.Index(elemIdx)
+ nv, err := d.descend(elem, path, idx, expr, value)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ if nv.IsValid() {
+ elem.Set(nv)
+ }
+ return v, nil
+ default:
+ return reflect.Value{}, d.typeMismatchError("table", v.Type(), keyHighlight(d.p.Data(), part.node))
}
-
- return nil
}
-func (d *decoder) unmarshalDateTime(value *unstable.Node, v reflect.Value) error {
- dt, err := parseDateTime(value.Data)
- if err != nil {
- return err
+// descendStrMap assigns into a native map[string]interface{} target, following
+// the remaining dotted-key parts with plain Go map operations and decoding the
+// value with decodeAny. It returns the map to store back at this level: a new
+// map when v was nil, otherwise v unchanged, since maps are reference types and
+// are mutated in place.
+func (d *decoder) descendStrMap(v reflect.Value, path []pathPart, idx int, value *unstable.Node) (reflect.Value, error) {
+ var m map[string]interface{}
+ if v.IsNil() {
+ m = make(map[string]interface{})
+ v = reflect.ValueOf(m)
+ } else {
+ m = v.Interface().(map[string]interface{})
}
- v.Set(reflect.ValueOf(dt))
- return nil
-}
+ // Walk intermediate parts, creating or reusing nested generic maps. A
+ // non-map value at an intermediate key can only occur in a document the
+ // seen-tracker has already rejected; replacing it mirrors the reflect
+ // path (elemOrNewMap).
+ for ; idx < len(path)-1; idx++ {
+ name := d.partString(&path[idx])
+ child, _ := m[name].(map[string]interface{})
+ if child == nil {
+ child = make(map[string]interface{})
+ m[name] = child
+ }
+ m = child
+ }
-func (d *decoder) unmarshalLocalDate(value *unstable.Node, v reflect.Value) error {
- ld, err := parseLocalDate(value.Data)
+ av, err := d.decodeAny(value)
if err != nil {
- return err
+ return reflect.Value{}, err
}
+ m[d.partString(&path[idx])] = av
+ return v, nil
+}
- if v.Type() == timeType {
- cast := ld.AsTime(time.Local)
- v.Set(reflect.ValueOf(cast))
- return nil
+// keyHighlight returns a highlight for the given key part node, falling back
+// to the start of the document.
+func keyHighlight(doc []byte, node *unstable.Node) []byte {
+ if node == nil {
+ return doc[0:0]
}
-
- v.Set(reflect.ValueOf(ld))
-
- return nil
+ return doc[node.Raw.Offset : node.Raw.Offset+node.Raw.Length]
}
-func (d *decoder) unmarshalLocalTime(value *unstable.Node, v reflect.Value) error {
- lt, rest, err := parseLocalTime(value.Data)
- if err != nil {
- return err
+// rawValue returns the raw bytes of the value of a key-value expression.
+func (d *decoder) rawValue(expr *unstable.Node, value *unstable.Node) []byte {
+ if value.Kind != unstable.InlineTable && value.Kind != unstable.Array {
+ return d.p.Raw(value.Raw)
}
-
- if len(rest) > 0 {
- return unstable.NewParserError(rest, "extra characters at the end of a local time")
+ if expr == nil || expr.Kind != unstable.KeyValue {
+ // Inline container nested in another container: best effort.
+ return d.p.Raw(value.Raw)
}
-
- v.Set(reflect.ValueOf(lt))
- return nil
+ // Reconstruct the span of the value: it starts after the equal sign
+ // following the last part of the key, and stops at the end of the
+ // expression.
+ var last unstable.Range
+ it := expr.Key()
+ for it.Next() {
+ last = it.Node().Raw
+ }
+ doc := d.p.Data()
+ i := int(last.Offset + last.Length)
+ for i < len(doc) && (doc[i] == ' ' || doc[i] == '\t') {
+ i++
+ }
+ i++ // equal sign
+ for i < len(doc) && (doc[i] == ' ' || doc[i] == '\t') {
+ i++
+ }
+ end := int(expr.Raw.Offset + expr.Raw.Length)
+ return doc[i:end]
}
-func (d *decoder) unmarshalLocalDateTime(value *unstable.Node, v reflect.Value) error {
- ldt, rest, err := parseLocalDateTime(value.Data)
- if err != nil {
- return err
+// unmarshalerOf returns the unstable.Unmarshaler implementation of v, if
+// any. It allocates intermediate pointers as needed.
+func unmarshalerOf(v reflect.Value) (unstable.Unmarshaler, bool) {
+ t := v.Type()
+ if t.Implements(unmarshalerType) {
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ v.Set(reflect.New(t.Elem()))
+ }
+ return v.Interface().(unstable.Unmarshaler), true
}
-
- if len(rest) > 0 {
- return unstable.NewParserError(rest, "extra characters at the end of a local date time")
+ if v.CanAddr() && reflect.PtrTo(t).Implements(unmarshalerType) {
+ return v.Addr().Interface().(unstable.Unmarshaler), true
}
+ return nil, false
+}
- if v.Type() == timeType {
- cast := ldt.AsTime(time.Local)
+var unmarshalerType = reflect.TypeOf(new(unstable.Unmarshaler)).Elem()
- v.Set(reflect.ValueOf(cast))
- return nil
+// assignValue stores the TOML value carried by the node into v.
+func (d *decoder) assignValue(v reflect.Value, expr *unstable.Node, value *unstable.Node) (reflect.Value, error) {
+ if v.Kind() == reflect.Ptr {
+ if d.unmarshalerInterface {
+ if u, ok := unmarshalerOf(v); ok {
+ return v, u.UnmarshalTOML(d.rawValue(expr, value))
+ }
+ }
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ nv, err := d.assignValue(v.Elem(), expr, value)
+ if err != nil || !nv.IsValid() {
+ return reflect.Value{}, err
+ }
+ v.Elem().Set(nv)
+ return v, nil
}
- v.Set(reflect.ValueOf(ldt))
-
- return nil
-}
-
-func (d *decoder) unmarshalBool(value *unstable.Node, v reflect.Value) error {
- b := value.Data[0] == 't'
+ if d.unmarshalerInterface {
+ if u, ok := unmarshalerOf(v); ok {
+ return v, u.UnmarshalTOML(d.rawValue(expr, value))
+ }
+ }
- switch v.Kind() {
- case reflect.Bool:
- v.SetBool(b)
- case reflect.Interface:
- v.Set(reflect.ValueOf(b))
+ switch value.Kind {
+ case unstable.String:
+ return d.assignString(v, value)
+ case unstable.Integer:
+ return d.assignInteger(v, value)
+ case unstable.Float:
+ return d.assignFloat(v, value)
+ case unstable.Bool:
+ return d.assignBool(v, value)
+ case unstable.DateTime:
+ return d.assignDateTime(v, value)
+ case unstable.LocalDateTime:
+ return d.assignLocalDateTime(v, value)
+ case unstable.LocalDate:
+ return d.assignLocalDate(v, value)
+ case unstable.LocalTime:
+ return d.assignLocalTime(v, value)
+ case unstable.Array:
+ return d.assignArray(v, expr, value)
+ case unstable.InlineTable:
+ return d.assignInlineTable(v, expr, value)
default:
- return unstable.NewParserError(value.Data, "cannot assign boolean to a %t", b)
+ return reflect.Value{}, unstable.NewParserError(value.Data, "unsupported value kind %s", value.Kind)
}
-
- return nil
}
-func (d *decoder) unmarshalFloat(value *unstable.Node, v reflect.Value) error {
- f, err := parseFloat(value.Data)
- if err != nil {
- return err
- }
-
+func (d *decoder) assignString(v reflect.Value, value *unstable.Node) (reflect.Value, error) {
switch v.Kind() {
- case reflect.Float64:
- v.SetFloat(f)
- case reflect.Float32:
- if f > math.MaxFloat32 {
- return unstable.NewParserError(value.Data, "number %f does not fit in a float32", f)
- }
- v.SetFloat(f)
+ case reflect.String:
+ v.SetString(string(value.Data))
+ return v, nil
case reflect.Interface:
- v.Set(reflect.ValueOf(f))
+ return boxInto(v, reflect.ValueOf(string(value.Data)))
default:
- return unstable.NewParserError(value.Data, "float cannot be assigned to %s", v.Kind())
}
-
- return nil
-}
-
-const (
- maxInt = int64(^uint(0) >> 1)
- minInt = -maxInt - 1
-)
-
-// Maximum value of uint for decoding. Currently the decoder parses the integer
-// into an int64. As a result, on architectures where uint is 64 bits, the
-// effective maximum uint we can decode is the maximum of int64. On
-// architectures where uint is 32 bits, the maximum value we can decode is
-// lower: the maximum of uint32. I didn't find a way to figure out this value at
-// compile time, so it is computed during initialization.
-var maxUint int64 = math.MaxInt64
-
-func init() {
- m := uint64(^uint(0))
- if m < uint64(maxUint) {
- maxUint = int64(m)
+ if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {
+ err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(value.Data)
+ if err != nil {
+ return reflect.Value{}, unstable.NewParserError(d.p.Raw(value.Raw), "%s", err)
+ }
+ return v, nil
}
+ return reflect.Value{}, d.typeMismatchError("string", v.Type(), d.p.Raw(value.Raw))
}
-func (d *decoder) unmarshalInteger(value *unstable.Node, v reflect.Value) error {
- kind := v.Kind()
- if kind == reflect.Float32 || kind == reflect.Float64 {
- return d.unmarshalFloat(value, v)
+func (d *decoder) assignInteger(v reflect.Value, value *unstable.Node) (reflect.Value, error) {
+ // Integer values targeting a float field are parsed as floats: they can
+ // represent (approximately) numbers beyond the int64 range.
+ if k := v.Kind(); k == reflect.Float32 || k == reflect.Float64 {
+ return d.assignFloat(v, value)
}
i, err := parseInteger(value.Data)
if err != nil {
- return err
+ return reflect.Value{}, err
}
- var r reflect.Value
-
- switch kind {
- case reflect.Int64:
- v.SetInt(i)
- return nil
- case reflect.Int32:
- if i < math.MinInt32 || i > math.MaxInt32 {
- return fmt.Errorf("toml: number %d does not fit in an int32", i)
- }
-
- r = reflect.ValueOf(int32(i))
- case reflect.Int16:
- if i < math.MinInt16 || i > math.MaxInt16 {
- return fmt.Errorf("toml: number %d does not fit in an int16", i)
- }
-
- r = reflect.ValueOf(int16(i))
- case reflect.Int8:
- if i < math.MinInt8 || i > math.MaxInt8 {
- return fmt.Errorf("toml: number %d does not fit in an int8", i)
- }
-
- r = reflect.ValueOf(int8(i))
- case reflect.Int:
- if i < minInt || i > maxInt {
- return fmt.Errorf("toml: number %d does not fit in an int", i)
+ switch v.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ if v.OverflowInt(i) {
+ return reflect.Value{}, unstable.NewParserError(value.Data, "integer value %d cannot be stored in %s", i, v.Type())
}
-
- r = reflect.ValueOf(int(i))
- case reflect.Uint64:
+ v.SetInt(i)
+ return v, nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
if i < 0 {
- return fmt.Errorf("toml: negative number %d does not fit in an uint64", i)
+ return reflect.Value{}, unstable.NewParserError(value.Data, "negative integer value %d cannot be stored in %s", i, v.Type())
}
-
- r = reflect.ValueOf(uint64(i))
- case reflect.Uint32:
- if i < 0 || i > math.MaxUint32 {
- return fmt.Errorf("toml: negative number %d does not fit in an uint32", i)
+ if v.OverflowUint(uint64(i)) {
+ return reflect.Value{}, unstable.NewParserError(value.Data, "integer value %d cannot be stored in %s", i, v.Type())
}
+ v.SetUint(uint64(i))
+ return v, nil
+ case reflect.Interface:
+ return boxInto(v, reflect.ValueOf(i))
+ default:
+ }
+ if ok, err := tryTextUnmarshaler(v, value.Data); ok {
+ return v, err
+ }
+ return reflect.Value{}, d.typeMismatchError("integer", v.Type(), d.p.Raw(value.Raw))
+}
- r = reflect.ValueOf(uint32(i))
- case reflect.Uint16:
- if i < 0 || i > math.MaxUint16 {
- return fmt.Errorf("toml: negative number %d does not fit in an uint16", i)
- }
+// tryTextUnmarshaler attempts to deliver the raw text of a value to a target
+// implementing encoding.TextUnmarshaler.
+func tryTextUnmarshaler(v reflect.Value, text []byte) (bool, error) {
+ if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {
+ return true, v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(text)
+ }
+ return false, nil
+}
- r = reflect.ValueOf(uint16(i))
- case reflect.Uint8:
- if i < 0 || i > math.MaxUint8 {
- return fmt.Errorf("toml: negative number %d does not fit in an uint8", i)
- }
+func (d *decoder) assignFloat(v reflect.Value, value *unstable.Node) (reflect.Value, error) {
+ f, err := parseFloat(value.Data)
+ if err != nil {
+ return reflect.Value{}, err
+ }
- r = reflect.ValueOf(uint8(i))
- case reflect.Uint:
- if i < 0 || i > maxUint {
- return fmt.Errorf("toml: negative number %d does not fit in an uint", i)
+ switch v.Kind() {
+ case reflect.Float64:
+ v.SetFloat(f)
+ return v, nil
+ case reflect.Float32:
+ if !math.IsInf(f, 0) && math.Abs(f) > math.MaxFloat32 {
+ return reflect.Value{}, unstable.NewParserError(value.Data, "float value %f cannot be stored in float32", f)
}
-
- r = reflect.ValueOf(uint(i))
+ v.SetFloat(f)
+ return v, nil
case reflect.Interface:
- r = reflect.ValueOf(i)
+ return boxInto(v, reflect.ValueOf(f))
default:
- return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("integer", v.Type()))
}
-
- if !r.Type().AssignableTo(v.Type()) {
- r = r.Convert(v.Type())
+ if ok, err := tryTextUnmarshaler(v, value.Data); ok {
+ return v, err
}
-
- v.Set(r)
-
- return nil
+ return reflect.Value{}, d.typeMismatchError("float", v.Type(), d.p.Raw(value.Raw))
}
-func (d *decoder) unmarshalString(value *unstable.Node, v reflect.Value) error {
+func (d *decoder) assignBool(v reflect.Value, value *unstable.Node) (reflect.Value, error) {
+ b := value.Data[0] == 't'
+
switch v.Kind() {
- case reflect.String:
- v.SetString(string(value.Data))
+ case reflect.Bool:
+ v.SetBool(b)
+ return v, nil
case reflect.Interface:
- v.Set(reflect.ValueOf(string(value.Data)))
+ return boxInto(v, reflect.ValueOf(b))
default:
- return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("string", v.Type()))
}
-
- return nil
+ if ok, err := tryTextUnmarshaler(v, value.Data); ok {
+ return v, err
+ }
+ return reflect.Value{}, d.typeMismatchError("boolean", v.Type(), d.p.Raw(value.Raw))
}
-func (d *decoder) handleKeyValue(expr *unstable.Node, v reflect.Value) (reflect.Value, error) {
- d.strict.EnterKeyValue(expr)
+func (d *decoder) assignDateTime(v reflect.Value, value *unstable.Node) (reflect.Value, error) {
+ t, err := parseDateTime(value.Data)
+ if err != nil {
+ return reflect.Value{}, err
+ }
- v, err := d.handleKeyValueInner(expr.Key(), expr.Value(), v)
- if d.skipUntilTable {
- d.strict.MissingField(expr)
- d.skipUntilTable = false
+ if v.Type() == timeType {
+ setConcrete(v, t)
+ return v, nil
+ }
+ if v.Kind() == reflect.Interface {
+ return boxInto(v, reflect.ValueOf(t))
}
+ return reflect.Value{}, d.typeMismatchError("datetime", v.Type(), d.p.Raw(value.Raw))
+}
+
+// setConcrete assigns x to v, which must be a settable value of x's concrete
+// type. Writing through the address avoids the heap allocation that
+// v.Set(reflect.ValueOf(x)) incurs from boxing x into an interface. Settable
+// implies addressable: the decoder assigns to struct fields, slice elements,
+// and reflect.New-allocated temporaries (map elements are decoded into such
+// temporaries), all of which are addressable.
+func setConcrete[T any](v reflect.Value, x T) {
+ *(v.Addr().Interface().(*T)) = x
+}
- d.strict.ExitKeyValue(expr)
+func (d *decoder) assignLocalDateTime(v reflect.Value, value *unstable.Node) (reflect.Value, error) {
+ dt, rest, err := parseLocalDateTime(value.Data)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ if len(rest) > 0 {
+ return reflect.Value{}, unstable.NewParserError(rest, "extra characters at the end of a local date time")
+ }
- return v, err
+ switch v.Type() {
+ case localDateTimeType:
+ setConcrete(v, dt)
+ return v, nil
+ case timeType:
+ setConcrete(v, dt.AsTime(time.Local))
+ return v, nil
+ }
+ if v.Kind() == reflect.Interface {
+ return boxInto(v, reflect.ValueOf(dt))
+ }
+ return reflect.Value{}, d.typeMismatchError("local datetime", v.Type(), d.p.Raw(value.Raw))
}
-func (d *decoder) handleKeyValueInner(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) {
- if key.Next() {
- // Still scoping the key
- return d.handleKeyValuePart(key, value, v)
+func (d *decoder) assignLocalDate(v reflect.Value, value *unstable.Node) (reflect.Value, error) {
+ date, err := parseLocalDate(value.Data)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+
+ switch v.Type() {
+ case localDateType:
+ setConcrete(v, date)
+ return v, nil
+ case timeType:
+ setConcrete(v, date.AsTime(time.Local))
+ return v, nil
}
- // Done scoping the key.
- // v is whatever Go value we need to fill.
- return reflect.Value{}, d.handleValue(value, v)
+ if v.Kind() == reflect.Interface {
+ return boxInto(v, reflect.ValueOf(date))
+ }
+ return reflect.Value{}, d.typeMismatchError("local date", v.Type(), d.p.Raw(value.Raw))
}
-func (d *decoder) keyFromData(keyType reflect.Type, data []byte) (reflect.Value, error) {
- switch {
- case stringType.AssignableTo(keyType):
- return reflect.ValueOf(string(data)), nil
+func (d *decoder) assignLocalTime(v reflect.Value, value *unstable.Node) (reflect.Value, error) {
+ t, rest, err := parseLocalTime(value.Data)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ if len(rest) > 0 {
+ return reflect.Value{}, unstable.NewParserError(rest, "extra characters at the end of a local time")
+ }
- case stringType.ConvertibleTo(keyType):
- return reflect.ValueOf(string(data)).Convert(keyType), nil
+ switch v.Type() {
+ case localTimeType:
+ setConcrete(v, t)
+ return v, nil
+ case timeType:
+ setConcrete(v, time.Date(0, 1, 1, t.Hour, t.Minute, t.Second, t.Nanosecond, time.Local))
+ return v, nil
+ }
+ if v.Kind() == reflect.Interface {
+ return boxInto(v, reflect.ValueOf(t))
+ }
+ return reflect.Value{}, d.typeMismatchError("local time", v.Type(), d.p.Raw(value.Raw))
+}
- case keyType.Implements(textUnmarshalerType):
- mk := reflect.New(keyType.Elem())
- if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
- return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err)
+func (d *decoder) assignArray(v reflect.Value, expr *unstable.Node, value *unstable.Node) (reflect.Value, error) {
+ // Count the elements to allocate the target in one go.
+ count := 0
+ cit := value.Children()
+ for cit.Next() {
+ if cit.Node().Kind != unstable.Comment {
+ count++
}
- return mk, nil
+ }
- case reflect.PointerTo(keyType).Implements(textUnmarshalerType):
- mk := reflect.New(keyType)
- if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
- return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err)
+ switch v.Kind() {
+ case reflect.Slice:
+ // Allocate the backing array once at its final length and assign each
+ // element in place. This avoids a reflect.New allocation per element
+ // and the repeated growth checks of reflect.Append.
+ slice := reflect.MakeSlice(v.Type(), count, count)
+ i := 0
+ it := value.Children()
+ for it.Next() {
+ n := it.Node()
+ if n.Kind == unstable.Comment {
+ continue
+ }
+ elem := slice.Index(i)
+ nv, err := d.assignValue(elem, nil, n)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ if nv.IsValid() {
+ elem.Set(nv)
+ }
+ i++
}
- return mk.Elem(), nil
-
- case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64:
- key, err := strconv.ParseInt(string(data), 10, 64)
- if err != nil {
- return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from integer: %w", stringType, err)
+ return slice, nil
+ case reflect.Array:
+ it := value.Children()
+ i := 0
+ for it.Next() {
+ n := it.Node()
+ if n.Kind == unstable.Comment {
+ continue
+ }
+ if i >= v.Len() {
+ // Extra elements are dropped when the target array is too
+ // small.
+ break
+ }
+ elem := v.Index(i)
+ nv, err := d.assignValue(elem, nil, n)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ elem.Set(nv)
+ i++
}
- return reflect.ValueOf(key).Convert(keyType), nil
- case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64:
- key, err := strconv.ParseUint(string(data), 10, 64)
- if err != nil {
- return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from unsigned integer: %w", stringType, err)
+ return v, nil
+ case reflect.Interface:
+ // Build the []interface{} natively: each element is decoded straight
+ // into a Go value with no intermediate addressable reflect.Value and
+ // no reflect round-trip, and nested arrays recurse the same way.
+ slice := make([]interface{}, 0, count)
+ it := value.Children()
+ for it.Next() {
+ n := it.Node()
+ if n.Kind == unstable.Comment {
+ continue
+ }
+ ev, err := d.decodeAny(n)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ slice = append(slice, ev)
}
- return reflect.ValueOf(key).Convert(keyType), nil
+ return boxInto(v, reflect.ValueOf(slice))
+ default:
+ }
+ return reflect.Value{}, d.typeMismatchError("array", v.Type(), d.rawValue(expr, value))
+}
- case keyType.Kind() == reflect.Float32:
- key, err := strconv.ParseFloat(string(data), 32)
+// decodeAny decodes a value node into a native Go value (the representation
+// used for interface{} targets), without going through reflect. Scalars and
+// arrays are handled directly; inline tables still defer to the reflect-based
+// path so that their dotted-key merge semantics remain identical.
+func (d *decoder) decodeAny(n *unstable.Node) (interface{}, error) {
+ switch n.Kind {
+ case unstable.String:
+ return string(n.Data), nil
+ case unstable.Integer:
+ i, err := parseInteger(n.Data)
+ return i, err
+ case unstable.Float:
+ f, err := parseFloat(n.Data)
+ return f, err
+ case unstable.Bool:
+ return n.Data[0] == 't', nil
+ case unstable.Array:
+ count := 0
+ cit := n.Children()
+ for cit.Next() {
+ if cit.Node().Kind != unstable.Comment {
+ count++
+ }
+ }
+ slice := make([]interface{}, 0, count)
+ it := n.Children()
+ for it.Next() {
+ c := it.Node()
+ if c.Kind == unstable.Comment {
+ continue
+ }
+ ev, err := d.decodeAny(c)
+ if err != nil {
+ return nil, err
+ }
+ slice = append(slice, ev)
+ }
+ return slice, nil
+ case unstable.InlineTable:
+ // Build the map natively: navigate each (possibly dotted) key with
+ // plain Go map operations and decode each value with decodeAny. The
+ // seen-tracker has already rejected duplicate or conflicting keys, so
+ // intermediate parts can be created/merged without revalidation.
+ count := 0
+ cit := n.Children()
+ for cit.Next() {
+ count++
+ }
+ m := make(map[string]interface{}, count)
+ it := n.Children()
+ for it.Next() {
+ kv := it.Node()
+ if err := d.setAnyKey(m, kv.Key(), kv.Value()); err != nil {
+ return nil, err
+ }
+ }
+ return m, nil
+ case unstable.DateTime:
+ t, err := parseDateTime(n.Data)
+ return t, err
+ case unstable.LocalDateTime:
+ dt, rest, err := parseLocalDateTime(n.Data)
if err != nil {
- return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err)
+ return nil, err
}
- return reflect.ValueOf(float32(key)), nil
-
- case keyType.Kind() == reflect.Float64:
- key, err := strconv.ParseFloat(string(data), 64)
+ if len(rest) > 0 {
+ return nil, unstable.NewParserError(rest, "extra characters at the end of a local date time")
+ }
+ return dt, nil
+ case unstable.LocalDate:
+ date, err := parseLocalDate(n.Data)
+ return date, err
+ case unstable.LocalTime:
+ t, rest, err := parseLocalTime(n.Data)
if err != nil {
- return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err)
+ return nil, err
}
- return reflect.ValueOf(float64(key)), nil
+ if len(rest) > 0 {
+ return nil, unstable.NewParserError(rest, "extra characters at the end of a local time")
+ }
+ return t, nil
+ default:
+ return nil, unstable.NewParserError(n.Data, "unsupported value kind %s", n.Kind)
}
- return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType)
}
-func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) {
- // contains the replacement for v
- var rv reflect.Value
-
- // First, dispatch over v to make sure it is a valid object.
- // There is no guarantee over what it could be.
+func (d *decoder) assignInlineTable(v reflect.Value, expr *unstable.Node, value *unstable.Node) (reflect.Value, error) {
switch v.Kind() {
case reflect.Map:
- vt := v.Type()
-
- mk, err := d.keyFromData(vt.Key(), key.Node().Data)
+ // Inline tables are self-contained: they fully replace the target.
+ v = reflect.MakeMap(v.Type())
+ case reflect.Struct:
+ // fields are set in place
+ case reflect.Interface:
+ elem := reflect.ValueOf(map[string]interface{}{})
+ nv, err := d.assignInlineTable(elem, expr, value)
if err != nil {
return reflect.Value{}, err
}
+ return boxInto(v, nv)
+ default:
+ return reflect.Value{}, d.typeMismatchError("inline table", v.Type(), d.rawValue(expr, value))
+ }
- // If the map does not exist, create it.
- if v.IsNil() {
- v = reflect.MakeMap(vt)
- rv = v
- }
-
- mv := v.MapIndex(mk)
- set := false
- if !mv.IsValid() || key.IsLast() {
- set = true
- mv = reflect.New(v.Type().Elem()).Elem()
- }
-
- nv, err := d.handleKeyValueInner(key, value, mv)
+ it := value.Children()
+ for it.Next() {
+ kv := it.Node()
+ // Build the path from the key of this key-value. Keys of inline
+ // tables rarely have more than a few parts.
+ var pathBuf [4]pathPart
+ path := pathBuf[:0]
+ kit := kv.Key()
+ for kit.Next() {
+ path = append(path, pathPart{node: kit.Node()})
+ }
+ nv, err := d.descend(v, path, 0, kv, kv.Value())
if err != nil {
return reflect.Value{}, err
}
if nv.IsValid() {
- mv = nv
- set = true
- }
-
- if set {
- v.SetMapIndex(mk, mv)
+ v = nv
}
- case reflect.Struct:
- path, found := structFieldPath(v, string(key.Node().Data))
- if !found {
- d.skipUntilTable = true
- break
- }
-
- if d.errorContext == nil {
- d.errorContext = new(errorContext)
- }
- t := v.Type()
- d.errorContext.Struct = t
- d.errorContext.Field = path
+ }
+ return v, nil
+}
- f := fieldByIndex(v, path)
+// boxInto returns the value to store in place of the interface value v. The
+// caller stores the result in the slot v was found in, which performs the
+// interface conversion, so the concrete value can be returned as-is.
+func boxInto(v reflect.Value, c reflect.Value) (reflect.Value, error) {
+ if !c.Type().AssignableTo(v.Type()) {
+ return reflect.Value{}, fmt.Errorf("toml: cannot store %s into %s", c.Type(), v.Type())
+ }
+ return c, nil
+}
- if !f.CanAddr() {
- // If the field is not addressable, need to take a slower path and
- // make a copy of the struct itself to a new location.
- nvp := reflect.New(v.Type())
- nvp.Elem().Set(v)
- v = nvp.Elem()
- _, err := d.handleKeyValuePart(key, value, v)
- if err != nil {
- return reflect.Value{}, err
- }
- return nvp.Elem(), nil
- }
- x, err := d.handleKeyValueInner(key, value, f)
- if err != nil {
- return reflect.Value{}, err
- }
+var (
+ interfaceType = reflect.TypeOf(new(interface{})).Elem()
+ localDateType = reflect.TypeOf(LocalDate{})
+ localTimeType = reflect.TypeOf(LocalTime{})
+ localDateTimeType = reflect.TypeOf(LocalDateTime{})
+)
- if x.IsValid() {
- f.Set(x)
- }
- d.errorContext.Struct = nil
- d.errorContext.Field = nil
- case reflect.Interface:
- v = v.Elem()
+// structPlan caches the mapping between TOML keys and the fields of a struct
+// type. byFold, keyed by the lowercased name, resolves any key on its own when
+// no two fields fold to the same name (the overwhelmingly common case, marked
+// by hasCollision == false): TOML keys are usually lowercase and never match
+// the exact (capitalized) Go field names, so the byName probe was always a
+// wasted lookup. byName (the exact names) is only consulted, first, when
+// fields do collide under folding, to preserve the exact-match-wins tiebreak.
+type structPlan struct {
+ byName map[string]structField
+ byFold map[string]structField
+ hasCollision bool
+}
- // Following encoding/json: decoding an object into an
- // interface{}, it needs to always hold a
- // map[string]interface{}. This is for the types to be
- // consistent whether a previous value was set or not.
- if !v.IsValid() || v.Type() != mapStringInterfaceType {
- v = makeMapStringInterface()
- }
+type structField struct {
+ index []int
+ fieldName string
+}
- x, err := d.handleKeyValuePart(key, value, v)
- if err != nil {
- return reflect.Value{}, err
- }
- if x.IsValid() {
- v = x
- }
- rv = v
- case reflect.Ptr:
- elem := v.Elem()
- if !elem.IsValid() {
- ptr := reflect.New(v.Type().Elem())
- v.Set(ptr)
- rv = v
- elem = ptr.Elem()
+// foldBufSize bounds the stack buffer used to lowercase keys without
+// allocating. Keys longer than this (extremely rare) take the strings.ToLower
+// fallback.
+const foldBufSize = 68
+
+// lookup and lookupBytes keep the hot path to a single inlinable byFold lookup.
+// byFold is indexed by both the exact field/tag names and their lowercased
+// forms, so that lookup resolves the two common cases — a lowercase key, or a
+// key matching the field's own casing — directly. byName is consulted first
+// only for types whose fields collide under case-folding, to preserve the
+// exact-match-wins tiebreak. The buffer-fold for other casings lives
+// out-of-line so it does not bloat the hot path.
+func (p *structPlan) lookup(name string) (structField, bool) {
+ if p.hasCollision {
+ if f, ok := p.byName[name]; ok {
+ return f, true
}
+ }
+ if f, ok := p.byFold[name]; ok {
+ return f, true
+ }
+ return p.lookupFoldStr(name)
+}
- elem2, err := d.handleKeyValuePart(key, value, elem)
- if err != nil {
- return reflect.Value{}, err
+func (p *structPlan) lookupBytes(name []byte) (structField, bool) {
+ if p.hasCollision {
+ if f, ok := p.byName[string(name)]; ok { // does not allocate
+ return f, true
}
- if elem2.IsValid() {
- elem = elem2
- }
- v.Elem().Set(elem)
- default:
- return reflect.Value{}, fmt.Errorf("unhandled kv part: %s", v.Kind())
}
-
- return rv, nil
+ if f, ok := p.byFold[string(name)]; ok { // does not allocate
+ return f, true
+ }
+ return p.lookupFold(name)
}
-func initAndDereferencePointer(v reflect.Value) reflect.Value {
- var elem reflect.Value
- if v.IsNil() {
- ptr := reflect.New(v.Type().Elem())
- v.Set(ptr)
+// lookupFold resolves keys whose casing matches neither the exact nor the
+// lowercased index: it folds to lowercase (in a stack buffer for ASCII, so no
+// allocation) and retries; only non-ASCII or oversized keys hit strings.ToLower.
+func (p *structPlan) lookupFold(name []byte) (structField, bool) {
+ if len(name) <= foldBufSize {
+ // Fold into a stack buffer: len(name) <= cap(buf), so the append
+ // never reallocates and nothing escapes to the heap.
+ var buf [foldBufSize]byte
+ b := buf[:0]
+ ascii := true
+ for _, c := range name {
+ if c >= 0x80 {
+ ascii = false
+ break
+ }
+ if c >= 'A' && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+ b = append(b, c)
+ }
+ if ascii {
+ f, ok := p.byFold[string(b)] // does not allocate
+ return f, ok
+ }
}
- elem = v.Elem()
- return elem
+ f, ok := p.byFold[strings.ToLower(string(name))]
+ return f, ok
}
-// Same as reflect.Value.FieldByIndex, but creates pointers if needed.
-func fieldByIndex(v reflect.Value, path []int) reflect.Value {
- for _, x := range path {
- v = v.Field(x)
-
- if v.Kind() == reflect.Ptr {
- if v.IsNil() {
- v.Set(reflect.New(v.Type().Elem()))
+func (p *structPlan) lookupFoldStr(name string) (structField, bool) {
+ if len(name) <= foldBufSize {
+ // Fold into a stack buffer: len(name) <= cap(buf), so the append
+ // never reallocates and nothing escapes to the heap.
+ var buf [foldBufSize]byte
+ b := buf[:0]
+ ascii := true
+ for i := 0; i < len(name); i++ {
+ c := name[i]
+ if c >= 0x80 {
+ ascii = false
+ break
+ }
+ if c >= 'A' && c <= 'Z' {
+ c += 'a' - 'A'
}
- v = v.Elem()
+ b = append(b, c)
+ }
+ if ascii {
+ f, ok := p.byFold[string(b)] // does not allocate
+ return f, ok
}
}
- return v
+ f, ok := p.byFold[strings.ToLower(name)]
+ return f, ok
}
-type fieldPathsMap = map[string][]int
-
-var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap
+var structPlans sync.Map // reflect.Type -> *structPlan
-func structFieldPath(v reflect.Value, name string) ([]int, bool) {
- t := v.Type()
-
- cache, _ := globalFieldPathsCache.Load().(map[danger.TypeID]fieldPathsMap)
- fieldPaths, ok := cache[danger.MakeTypeID(t)]
-
- if !ok {
- fieldPaths = map[string][]int{}
-
- forEachField(t, nil, func(name string, path []int) {
- fieldPaths[name] = path
- // extra copy for the case-insensitive match
- fieldPaths[strings.ToLower(name)] = path
- })
-
- newCache := make(map[danger.TypeID]fieldPathsMap, len(cache)+1)
- newCache[danger.MakeTypeID(t)] = fieldPaths
- for k, v := range cache {
- newCache[k] = v
- }
- globalFieldPathsCache.Store(newCache)
+func planForType(t reflect.Type) *structPlan {
+ if plan, ok := structPlans.Load(t); ok {
+ return plan.(*structPlan)
}
+ plan := buildPlan(t)
+ structPlans.Store(t, plan)
+ return plan
+}
- path, ok := fieldPaths[name]
- if !ok {
- path, ok = fieldPaths[strings.ToLower(name)]
+func buildPlan(t reflect.Type) *structPlan {
+ plan := &structPlan{
+ byName: map[string]structField{},
+ byFold: map[string]structField{},
}
- return path, ok
+ addFields(plan, t, nil, map[reflect.Type]bool{})
+ return plan
}
-func forEachField(t reflect.Type, path []int, do func(name string, path []int)) {
- n := t.NumField()
- for i := 0; i < n; i++ {
- f := t.Field(i)
+// addFields flattens the fields of t into the plan. visited holds the types
+// being flattened on the current branch: a struct type that embeds itself
+// (directly or through other types) is not descended into again, mirroring
+// buildEncPlan. Without this guard a recursive embedding would recurse
+// forever; the repeated fields are unreachable by flattening anyway.
+func addFields(plan *structPlan, t reflect.Type, prefix []int, visited map[reflect.Type]bool) {
+ if visited[t] {
+ return
+ }
+ visited[t] = true
+ defer delete(visited, t)
- if !f.Anonymous && f.PkgPath != "" {
- // only consider exported fields.
- continue
+ var embedded []reflect.StructField
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ tag, tagged := f.Tag.Lookup("toml")
+ name := f.Name
+ explicitName := ""
+ if tagged {
+ // A tag of exactly "-" drops the field. "-," names it "-".
+ if tag == "-" {
+ continue
+ }
+ parts := strings.SplitN(tag, ",", 2)
+ explicitName = parts[0]
+ if explicitName != "" {
+ name = explicitName
+ }
}
-
- fieldPath := append(path, i)
- fieldPath = fieldPath[:len(fieldPath):len(fieldPath)]
-
- name := f.Tag.Get("toml")
- if name == "-" {
+ if f.Anonymous {
+ ft := f.Type
+ if ft.Kind() == reflect.Ptr {
+ ft = ft.Elem()
+ }
+ if ft.Kind() != reflect.Struct {
+ // Embedded non-struct fields are not decoded into.
+ continue
+ }
+ if explicitName == "" {
+ // Embedded structs without an explicit tag name are flattened,
+ // even when their type is unexported: only their own exported
+ // fields are reachable. A tag that only sets options (e.g.
+ // `,inline`) still flattens, matching encoding/json and the
+ // encoder's behavior.
+ embedded = append(embedded, f)
+ continue
+ }
+ // An embedded struct given an explicit tag name acts as a regular
+ // named field.
+ } else if f.PkgPath != "" {
+ // unexported
continue
}
-
- if i := strings.IndexByte(name, ','); i >= 0 {
- name = name[:i]
+ index := make([]int, 0, len(prefix)+1)
+ index = append(index, prefix...)
+ index = append(index, i)
+ sf := structField{index: index, fieldName: f.Name}
+ if _, ok := plan.byName[name]; !ok {
+ plan.byName[name] = sf
}
-
- if f.Anonymous && name == "" {
- t2 := f.Type
- if t2.Kind() == reflect.Ptr {
- t2 = t2.Elem()
- }
-
- if t2.Kind() == reflect.Struct {
- forEachField(t2, fieldPath, do)
+ lower := strings.ToLower(name)
+ if _, ok := plan.byFold[lower]; !ok {
+ plan.byFold[lower] = sf
+ } else {
+ // Two distinct fields fold to the same name: case-insensitive
+ // matching is ambiguous, so lookups must consult byName first to
+ // keep the exact-match-wins tiebreak deterministic.
+ plan.hasCollision = true
+ }
+ // Index the exact (cased) name as well, so a key written with the
+ // field's own casing resolves in a single byFold lookup. Only fields
+ // whose name is not already lowercase need this extra entry. Any name
+ // that would conflict here also collides under folding (handled
+ // above), so byName-first preserves the exact tiebreak in that case.
+ if name != lower {
+ if _, ok := plan.byFold[name]; !ok {
+ plan.byFold[name] = sf
}
- continue
}
+ }
+ // Embedded structs are flattened after the regular fields, so that
+ // shallower fields win.
+ for _, f := range embedded {
+ ft := f.Type
+ if ft.Kind() == reflect.Ptr {
+ ft = ft.Elem()
+ }
+ index := make([]int, 0, len(prefix)+1)
+ index = append(index, prefix...)
+ idx := f.Index[0]
+ index = append(index, idx)
+ addFields(plan, ft, index, visited)
+ }
+}
- if name == "" {
- name = f.Name
+// fieldByIndexAlloc returns the field of v at the given index path,
+// allocating intermediate embedded pointers as needed.
+func fieldByIndexAlloc(v reflect.Value, index []int) (reflect.Value, error) {
+ // Fast path for non-embedded fields, which have a single-element index:
+ // no intermediate pointer dereferencing is possible.
+ if len(index) == 1 {
+ return v.Field(index[0]), nil
+ }
+ for i, x := range index {
+ if i > 0 {
+ for v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ if !v.CanSet() {
+ // A nil embedded pointer of unexported type cannot be
+ // allocated: reflect forbids setting it. Match
+ // encoding/json and report it instead of panicking.
+ return reflect.Value{}, fmt.Errorf("toml: cannot set embedded pointer to unexported struct: %s", v.Type().Elem())
+ }
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ }
}
-
- do(name, fieldPath)
+ v = v.Field(x)
}
+ return v, nil
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go b/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
index f526bf2c..2cf3bdb6 100644
--- a/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
@@ -1,10 +1,8 @@
package unstable
import (
+ "errors"
"fmt"
- "unsafe"
-
- "github.com/pelletier/go-toml/v2/internal/danger"
)
// Iterator over a sequence of nodes.
@@ -23,8 +21,8 @@ type Iterator struct {
node *Node
}
-// Next moves the iterator forward and returns true if points to a
-// node, false otherwise.
+// Next moves the iterator forward and returns true if points to a node, false
+// otherwise.
func (c *Iterator) Next() bool {
if !c.started {
c.started = true
@@ -35,7 +33,7 @@ func (c *Iterator) Next() bool {
}
// IsLast returns true if the current node of the iterator is the last
-// one. Subsequent calls to Next() will return false.
+// one. Subsequent calls to Next() will return false.
func (c *Iterator) IsLast() bool {
return c.node.next == 0
}
@@ -53,8 +51,8 @@ func (c *Iterator) Node() *Node {
// - Array have one child per element in the array.
// - InlineTable have one child per key-value in the table (each of kind
// InlineTable).
-// - KeyValue have at least two children. The first one is the value. The rest
-// make a potentially dotted key.
+// - KeyValue have at least two children. The first one is the value. The
+// rest make a potentially dotted key.
// - Table and ArrayTable's children represent a dotted key (same as
// KeyValue, but without the first node being the value).
//
@@ -65,17 +63,11 @@ type Node struct {
Raw Range // Raw bytes from the input.
Data []byte // Node value (either allocated or referencing the input).
- // References to other nodes, as offsets in the backing array
- // from this node. References can go backward, so those can be
- // negative.
- next int // 0 if last element
- child int // 0 if no child
-}
-
-// Range of bytes in the document.
-type Range struct {
- Offset uint32
- Length uint32
+ // References to other nodes, as 1-based indexes into the parser's arena.
+ // 0 means no node.
+ parser *Parser
+ next int32
+ child int32
}
// Next returns a pointer to the next node, or nil if there is no next node.
@@ -83,37 +75,33 @@ func (n *Node) Next() *Node {
if n.next == 0 {
return nil
}
- ptr := unsafe.Pointer(n)
- size := unsafe.Sizeof(Node{})
- return (*Node)(danger.Stride(ptr, size, n.next))
+ return &n.parser.nodes[n.next-1]
}
// Child returns a pointer to the first child node of this node. Other children
-// can be accessed calling Next on the first child. Returns an nil if this Node
-// has no child.
+// can be accessed calling Next on the first child. Returns nil if there is no
+// child node.
func (n *Node) Child() *Node {
if n.child == 0 {
return nil
}
- ptr := unsafe.Pointer(n)
- size := unsafe.Sizeof(Node{})
- return (*Node)(danger.Stride(ptr, size, n.child))
+ return &n.parser.nodes[n.child-1]
}
// Valid returns true if the node's kind is set (not to Invalid).
func (n *Node) Valid() bool {
- return n != nil
+ return n != nil && n.Kind != Invalid
}
// Key returns the children nodes making the Key on a supported node. Panics
-// otherwise. They are guaranteed to be all be of the Kind Key. A simple key
+// otherwise. They are guaranteed to be all be of the Kind Key. A simple key
// would return just one element.
func (n *Node) Key() Iterator {
switch n.Kind {
case KeyValue:
value := n.Child()
if !value.Valid() {
- panic(fmt.Errorf("KeyValue should have at least two children"))
+ panic(errors.New("KeyValue should have at least two children"))
}
return Iterator{node: value.Next()}
case Table, ArrayTable:
@@ -124,7 +112,7 @@ func (n *Node) Key() Iterator {
}
// Value returns a pointer to the value node of a KeyValue.
-// Guaranteed to be non-nil. Panics if not called on a KeyValue node,
+// Guaranteed to be non-nil. Panics if not called on a KeyValue node,
// or if the Children are malformed.
func (n *Node) Value() *Node {
return n.Child()
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/bridge.go b/vendor/github.com/pelletier/go-toml/v2/unstable/bridge.go
new file mode 100644
index 00000000..5482bde0
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/bridge.go
@@ -0,0 +1,21 @@
+package unstable
+
+import "github.com/pelletier/go-toml/v2/internal/parserbridge"
+
+// Expose the non-AST scanners to the root toml package without committing to
+// them in the public API. See internal/parserbridge for the rationale.
+//
+//nolint:gochecknoinits // load-time wiring of an internal bridge (see internal/parserbridge)
+func init() {
+ parserbridge.ScanScalar = func(p any, b []byte) (kind int, raw, value, rest []byte, err error) {
+ k, raw, value, rest, err := p.(*Parser).scanScalar(b)
+ return int(k), raw, value, rest, err
+ }
+ parserbridge.ScanKey = func(p any, b []byte, dst [][]byte) (parts [][]byte, raw, rest []byte, err error) {
+ return p.(*Parser).scanKey(b, dst)
+ }
+ parserbridge.ScanComment = scanComment
+ parserbridge.ParseValue = func(p any, b []byte) (node any, rest []byte, err error) {
+ return p.(*Parser).parseValue(b)
+ }
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go b/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go
deleted file mode 100644
index 9538e30d..00000000
--- a/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package unstable
-
-// root contains a full AST.
-//
-// It is immutable once constructed with Builder.
-type root struct {
- nodes []Node
-}
-
-// Iterator over the top level nodes.
-func (r *root) Iterator() Iterator {
- it := Iterator{}
- if len(r.nodes) > 0 {
- it.node = &r.nodes[0]
- }
- return it
-}
-
-func (r *root) at(idx reference) *Node {
- return &r.nodes[idx]
-}
-
-type reference int
-
-const invalidReference reference = -1
-
-func (r reference) Valid() bool {
- return r != invalidReference
-}
-
-type builder struct {
- tree root
- lastIdx int
-}
-
-func (b *builder) Tree() *root {
- return &b.tree
-}
-
-func (b *builder) NodeAt(ref reference) *Node {
- return b.tree.at(ref)
-}
-
-func (b *builder) Reset() {
- b.tree.nodes = b.tree.nodes[:0]
- b.lastIdx = 0
-}
-
-func (b *builder) Push(n Node) reference {
- b.lastIdx = len(b.tree.nodes)
- b.tree.nodes = append(b.tree.nodes, n)
- return reference(b.lastIdx)
-}
-
-func (b *builder) PushAndChain(n Node) reference {
- newIdx := len(b.tree.nodes)
- b.tree.nodes = append(b.tree.nodes, n)
- if b.lastIdx >= 0 {
- b.tree.nodes[b.lastIdx].next = newIdx - b.lastIdx
- }
- b.lastIdx = newIdx
- return reference(b.lastIdx)
-}
-
-func (b *builder) AttachChild(parent reference, child reference) {
- b.tree.nodes[parent].child = int(child) - int(parent)
-}
-
-func (b *builder) Chain(from reference, to reference) {
- b.tree.nodes[from].next = int(to) - int(from)
-}
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go b/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
index ff9df1be..f1912f77 100644
--- a/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
@@ -6,28 +6,40 @@ import "fmt"
type Kind int
const (
- // Meta
+ // Invalid represents an invalid meta node.
Invalid Kind = iota
+ // Comment represents a comment meta node.
Comment
+ // Key represents a key meta node.
Key
- // Top level structures
+ // Table represents a top-level table.
Table
+ // ArrayTable represents a top-level array table.
ArrayTable
+ // KeyValue represents a top-level key value.
KeyValue
- // Containers values
+ // Array represents an array container value.
Array
+ // InlineTable represents an inline table container value.
InlineTable
- // Values
+ // String represents a string value.
String
+ // Bool represents a boolean value.
Bool
+ // Float represents a floating point value.
Float
+ // Integer represents an integer value.
Integer
+ // LocalDate represents a local date value.
LocalDate
+ // LocalTime represents a local time value.
LocalTime
+ // LocalDateTime represents a local date/time value.
LocalDateTime
+ // DateTime represents a data/time value.
DateTime
)
@@ -67,5 +79,5 @@ func (k Kind) String() string {
case DateTime:
return "DateTime"
}
- panic(fmt.Errorf("Kind.String() not implemented for '%d'", k))
+ panic(fmt.Errorf("Kind.String() not implemented for kind %d", int(k)))
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/marshaler.go b/vendor/github.com/pelletier/go-toml/v2/unstable/marshaler.go
new file mode 100644
index 00000000..40c2e978
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/marshaler.go
@@ -0,0 +1,29 @@
+package unstable
+
+// Marshaler is implemented by types that can marshal themselves into a raw
+// TOML description. The returned bytes are spliced verbatim into the encoded
+// document, so they must be valid TOML for the position they end up in:
+//
+// - A single value (string, integer, array, inline table, …) is emitted
+// inline, as in `key = `.
+// - One or more key-value lines (optionally with relative sub-table headers)
+// is emitted as the body of a `[key]` table.
+// - At the document root, the bytes are emitted as the whole document.
+//
+// The encoder decides between those forms by parsing the returned bytes, and
+// reports an error when they are not valid TOML for their position; see
+// Encoder.EnableMarshalerInterface in the root toml package. MarshalTOML can
+// be called more than once for the same value during a single encode, so it
+// must be deterministic.
+//
+// Marshaler is the encoding counterpart of Unmarshaler.
+type Marshaler interface {
+ MarshalTOML() ([]byte, error)
+}
+
+// MarshalTOML implements Marshaler. It returns the raw TOML bytes verbatim,
+// mirroring json.RawMessage.MarshalJSON. The value receiver means both
+// RawMessage and *RawMessage satisfy Marshaler.
+func (m RawMessage) MarshalTOML() ([]byte, error) {
+ return []byte(m), nil
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go b/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
index 50358a44..cf72bb74 100644
--- a/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
@@ -2,11 +2,10 @@ package unstable
import (
"bytes"
+ "encoding/binary"
+ "errors"
"fmt"
- "unicode"
-
- "github.com/pelletier/go-toml/v2/internal/characters"
- "github.com/pelletier/go-toml/v2/internal/danger"
+ "unicode/utf8"
)
// ParserError describes an error relative to the content of the document.
@@ -43,23 +42,34 @@ func NewParserError(highlight []byte, format string, args ...interface{}) error
// Don't forget to check Error() after you're done parsing.
//
// Each top-level expression needs to be fully processed before calling
-// NextExpression() again. Otherwise, calls to various Node methods may panic if
-// the parser has moved on the next expression.
+// NextExpression() again. Otherwise, calls to various Node methods may panic
+// if the parser has moved on the next expression.
//
// For performance reasons, go-toml doesn't make a copy of the input bytes to
// the parser. Make sure to copy all the bytes you need to outlive the slice
// given to the parser.
type Parser struct {
- data []byte
- builder builder
- ref reference
- left []byte
- err error
- first bool
-
KeepComments bool
+
+ data []byte
+ left []byte
+ nodes []Node
+ err error
+
+ // nesting is the current depth of nested arrays and inline tables being
+ // parsed. It guards parseVal/parseValArray/parseInlineTable against
+ // unbounded mutual recursion, which would otherwise let a deeply nested
+ // document overflow the goroutine stack (an unrecoverable fatal error).
+ nesting int
}
+// maxValueNesting is the maximum depth of nested arrays and inline tables the
+// parser accepts. Beyond it, parsing fails with a ParserError instead of
+// risking a stack overflow. Real-world TOML documents nest only a handful of
+// levels deep, so this bound is generous; it matches the limit used by the
+// standard library's encoding/json.
+const maxValueNesting = 10000
+
// Data returns the slice provided to the last call to Reset.
func (p *Parser) Data() []byte {
return p.data
@@ -69,9 +79,17 @@ func (p *Parser) Data() []byte {
// input. If the argument is not a subslice of the parser input, this function
// panics.
func (p *Parser) Range(b []byte) Range {
+ // b is a subslice of p.data if and only if they share the same backing
+ // array. In that case, because subslicing cannot extend capacity, the
+ // number of bytes between the start of b and the end of the backing array
+ // (its capacity) identifies the offset of b within data.
+ offset := cap(p.data) - cap(b)
+ if offset < 0 || offset+len(b) > len(p.data) {
+ panic(errors.New("not a slice of the data slice"))
+ }
return Range{
- Offset: uint32(danger.SubsliceOffset(p.data, b)),
- Length: uint32(len(b)),
+ Offset: uint32(offset), //nolint:gosec // TOML documents are small
+ Length: uint32(len(b)), //nolint:gosec // TOML documents are small
}
}
@@ -83,58 +101,11 @@ func (p *Parser) Raw(raw Range) []byte {
// Reset brings the parser to its initial state for a given input. It wipes an
// reuses internal storage to reduce allocation.
func (p *Parser) Reset(b []byte) {
- p.builder.Reset()
- p.ref = invalidReference
p.data = b
p.left = b
+ p.nodes = p.nodes[:0]
p.err = nil
- p.first = true
-}
-
-// NextExpression parses the next top-level expression. If an expression was
-// successfully parsed, it returns true. If the parser is at the end of the
-// document or an error occurred, it returns false.
-//
-// Retrieve the parsed expression with Expression().
-func (p *Parser) NextExpression() bool {
- if len(p.left) == 0 || p.err != nil {
- return false
- }
-
- p.builder.Reset()
- p.ref = invalidReference
-
- for {
- if len(p.left) == 0 || p.err != nil {
- return false
- }
-
- if !p.first {
- p.left, p.err = p.parseNewline(p.left)
- }
-
- if len(p.left) == 0 || p.err != nil {
- return false
- }
-
- p.ref, p.left, p.err = p.parseExpression(p.left)
-
- if p.err != nil {
- return false
- }
-
- p.first = false
-
- if p.ref.Valid() {
- return true
- }
- }
-}
-
-// Expression returns a pointer to the node representing the last successfully
-// parsed expression.
-func (p *Parser) Expression() *Node {
- return p.builder.NodeAt(p.ref)
+ p.nesting = 0
}
// Error returns any error that has occurred during parsing.
@@ -142,6 +113,12 @@ func (p *Parser) Error() error {
return p.err
}
+// Range of bytes in the document.
+type Range struct {
+ Offset uint32
+ Length uint32
+}
+
// Position describes a position in the input.
type Position struct {
// Number of bytes from the beginning of the input.
@@ -158,16 +135,23 @@ type Shape struct {
End Position
}
-func (p *Parser) position(b []byte) Position {
- offset := danger.SubsliceOffset(p.data, b)
-
- lead := p.data[:offset]
-
- return Position{
+func (p *Parser) position(offset int) Position {
+ pos := Position{
Offset: offset,
- Line: bytes.Count(lead, []byte{'\n'}) + 1,
- Column: len(lead) - bytes.LastIndex(lead, []byte{'\n'}),
+ Line: 1,
+ Column: 1,
+ }
+ b := p.data[:offset]
+ for {
+ idx := bytes.IndexByte(b, '\n')
+ if idx < 0 {
+ break
+ }
+ pos.Line++
+ b = b[idx+1:]
}
+ pos.Column = len(b) + 1
+ return pos
}
// Shape returns the shape of the given range in the input. Will
@@ -175,1071 +159,1528 @@ func (p *Parser) position(b []byte) Position {
func (p *Parser) Shape(r Range) Shape {
raw := p.Raw(r)
return Shape{
- Start: p.position(raw),
- End: p.position(raw[r.Length:]),
+ Start: p.position(int(r.Offset)),
+ End: p.position(int(r.Offset) + len(raw)),
}
}
-func (p *Parser) parseNewline(b []byte) ([]byte, error) {
- if b[0] == '\n' {
- return b[1:], nil
+// Expression returns a pointer to the node representing the last successfully
+// parsed expression.
+func (p *Parser) Expression() *Node {
+ if len(p.nodes) == 0 {
+ return nil
}
+ return &p.nodes[0]
+}
- if b[0] == '\r' {
- _, rest, err := scanWindowsNewline(b)
- return rest, err
+// push appends a node to the arena and returns its handle (1-based index).
+func (p *Parser) push(n Node) int32 {
+ if len(p.nodes) == cap(p.nodes) {
+ // Grow by 2x: large expressions (huge arrays) would otherwise grow
+ // the arena in small steps, copying it repeatedly.
+ newCap := 2 * cap(p.nodes)
+ if newCap < 64 {
+ newCap = 64
+ }
+ nodes := make([]Node, len(p.nodes), newCap)
+ copy(nodes, p.nodes)
+ p.nodes = nodes
}
-
- return nil, NewParserError(b[0:1], "expected newline but got %#U", b[0])
+ n.parser = p
+ p.nodes = append(p.nodes, n)
+ return int32(len(p.nodes)) //nolint:gosec // node counts are bounded by document size
}
-func (p *Parser) parseComment(b []byte) (reference, []byte, error) {
- ref := invalidReference
- data, rest, err := scanComment(b)
- if p.KeepComments && err == nil {
- ref = p.builder.Push(Node{
- Kind: Comment,
- Raw: p.Range(data),
- Data: data,
- })
- }
- return ref, rest, err
+// at returns a pointer to the node with the given handle. Only valid until
+// the next call to push.
+func (p *Parser) at(handle int32) *Node {
+ return &p.nodes[handle-1]
}
-func (p *Parser) parseExpression(b []byte) (reference, []byte, error) {
- // expression = ws [ comment ]
- // expression =/ ws keyval ws [ comment ]
- // expression =/ ws table ws [ comment ]
- ref := invalidReference
-
- b = p.parseWhitespace(b)
+// offsetOf returns the offset of b within the parser's data. b must be a
+// subslice of p.data.
+func (p *Parser) offsetOf(b []byte) int {
+ return cap(p.data) - cap(b)
+}
- if len(b) == 0 {
- return ref, b, nil
+// rangeFrom returns the Range covering bytes from the start of `from` to the
+// start of `to`. Both must be subslices of p.data.
+func (p *Parser) rangeFrom(from, to []byte) Range {
+ start := p.offsetOf(from)
+ end := p.offsetOf(to)
+ return Range{
+ Offset: uint32(start), //nolint:gosec // TOML documents are small
+ Length: uint32(end - start), //nolint:gosec // TOML documents are small
}
+}
- if b[0] == '#' {
- ref, rest, err := p.parseComment(b)
- return ref, rest, err
+// NextExpression parses the next top-level expression. If an expression was
+// successfully parsed, it returns true. If the parser is at the end of the
+// document or an error occurred, it returns false.
+//
+// Retrieve the parsed expression with Expression().
+func (p *Parser) NextExpression() bool {
+ if p.err != nil {
+ return false
}
- if b[0] == '\n' || b[0] == '\r' {
- return ref, b, nil
- }
+ p.nodes = p.nodes[:0]
- var err error
- if b[0] == '[' {
- ref, b, err = p.parseTable(b)
- } else {
- ref, b, err = p.parseKeyval(b)
- }
+ for {
+ b := skipWhitespace(p.left)
+ if len(b) == 0 {
+ p.left = b
+ return false
+ }
- if err != nil {
- return ref, nil, err
+ var err error
+ switch b[0] {
+ case '\n':
+ p.left = b[1:]
+ continue
+ case '\r':
+ if len(b) > 1 && b[1] == '\n' {
+ p.left = b[2:]
+ continue
+ }
+ err = NewParserError(b[:1], "expected newline but got %#U", b[0])
+ case '#':
+ var comment, rest []byte
+ comment, rest, err = scanComment(b)
+ if err == nil {
+ rest, err = consumeEOL(rest)
+ }
+ if err == nil {
+ if p.KeepComments {
+ p.push(Node{
+ Kind: Comment,
+ Raw: p.Range(comment),
+ Data: comment,
+ })
+ p.left = rest
+ return true
+ }
+ p.left = rest
+ continue
+ }
+ case '[':
+ var rest []byte
+ rest, err = p.parseExprTable(b)
+ if err == nil {
+ p.left = rest
+ return true
+ }
+ default:
+ var rest []byte
+ rest, err = p.parseExprKeyval(b)
+ if err == nil {
+ p.left = rest
+ return true
+ }
+ }
+
+ // Errors at the end of the input have an empty highlight. Extend
+ // them to the last byte of the input so that they carry a usable
+ // position.
+ var perr *ParserError
+ if errors.As(err, &perr) && len(perr.Highlight) == 0 {
+ if offset := p.offsetOf(perr.Highlight); offset > 0 && offset == len(p.data) {
+ perr.Highlight = p.data[offset-1 : offset]
+ }
+ }
+
+ p.err = err
+ return false
}
+}
- b = p.parseWhitespace(b)
+// consumeEOL consumes a newline (LF or CRLF) or end of input.
+func consumeEOL(b []byte) ([]byte, error) {
+ if len(b) == 0 {
+ return b, nil
+ }
+ switch b[0] {
+ case '\n':
+ return b[1:], nil
+ case '\r':
+ if len(b) > 1 && b[1] == '\n' {
+ return b[2:], nil
+ }
+ }
+ return nil, NewParserError(b[:1], "expected newline but got %#U", b[0])
+}
+// finishLine handles `ws [comment] (newline|eof)` after a top-level
+// expression. If a comment is present and KeepComments is set, it is attached
+// as the next sibling of the expression's root node.
+func (p *Parser) finishLine(root int32, b []byte) ([]byte, error) {
+ b = skipWhitespace(b)
if len(b) > 0 && b[0] == '#' {
- cref, rest, err := p.parseComment(b)
- if cref != invalidReference {
- p.builder.Chain(ref, cref)
+ comment, rest, err := scanComment(b)
+ if err != nil {
+ return nil, err
+ }
+ if p.KeepComments {
+ h := p.push(Node{
+ Kind: Comment,
+ Raw: p.Range(comment),
+ Data: comment,
+ })
+ p.at(root).next = h
}
- return ref, rest, err
+ b = rest
}
+ return consumeEOL(b)
+}
- return ref, b, nil
+// parseExprKeyval parses a top-level `key = value` expression, including its
+// line termination.
+func (p *Parser) parseExprKeyval(b []byte) ([]byte, error) {
+ root, rest, err := p.parseKeyval(b)
+ if err != nil {
+ return nil, err
+ }
+ return p.finishLine(root, rest)
}
-func (p *Parser) parseTable(b []byte) (reference, []byte, error) {
- // table = std-table / array-table
+// parseExprTable parses a `[table]` or `[[array table]]` expression,
+// including its line termination. b starts at '['.
+func (p *Parser) parseExprTable(b []byte) ([]byte, error) {
+ var root int32
+ var err error
+ var rest []byte
if len(b) > 1 && b[1] == '[' {
- return p.parseArrayTable(b)
+ root, rest, err = p.parseArrayTableHeader(b)
+ } else {
+ root, rest, err = p.parseTableHeader(b)
}
-
- return p.parseStdTable(b)
+ if err != nil {
+ return nil, err
+ }
+ return p.finishLine(root, rest)
}
-func (p *Parser) parseArrayTable(b []byte) (reference, []byte, error) {
- // array-table = array-table-open key array-table-close
- // array-table-open = %x5B.5B ws ; [[ Double left square bracket
- // array-table-close = ws %x5D.5D ; ]] Double right square bracket
- ref := p.builder.Push(Node{
- Kind: ArrayTable,
- })
-
- b = b[2:]
- b = p.parseWhitespace(b)
+// parseTableHeader parses `[ ws key ws ]`. b starts at '['.
+func (p *Parser) parseTableHeader(b []byte) (int32, []byte, error) {
+ root := p.push(Node{Kind: Table})
- k, b, err := p.parseKey(b)
+ first, b, err := p.parseKey(skipWhitespace(b[1:]))
if err != nil {
- return ref, nil, err
+ return 0, nil, err
}
+ p.at(root).child = first
- p.builder.AttachChild(ref, k)
- b = p.parseWhitespace(b)
+ if len(b) == 0 || b[0] != ']' {
+ return 0, nil, NewParserError(highlight1(b), "expected ']' to close table name")
+ }
+ return root, b[1:], nil
+}
- b, err = expect(']', b)
+// parseArrayTableHeader parses `[[ ws key ws ]]`. b starts at '[['.
+func (p *Parser) parseArrayTableHeader(b []byte) (int32, []byte, error) {
+ root := p.push(Node{Kind: ArrayTable})
+
+ first, b, err := p.parseKey(skipWhitespace(b[2:]))
if err != nil {
- return ref, nil, err
+ return 0, nil, err
}
+ p.at(root).child = first
- b, err = expect(']', b)
-
- return ref, b, err
+ if len(b) < 2 || b[0] != ']' || b[1] != ']' {
+ return 0, nil, NewParserError(highlight1(b), "expected ']]' to close array table name")
+ }
+ return root, b[2:], nil
}
-func (p *Parser) parseStdTable(b []byte) (reference, []byte, error) {
- // std-table = std-table-open key std-table-close
- // std-table-open = %x5B ws ; [ Left square bracket
- // std-table-close = ws %x5D ; ] Right square bracket
- ref := p.builder.Push(Node{
- Kind: Table,
- })
-
- b = b[1:]
- b = p.parseWhitespace(b)
+// parseKeyval parses `key keyval-sep val`. Returns the handle to the KeyValue
+// node.
+func (p *Parser) parseKeyval(b []byte) (int32, []byte, error) {
+ root := p.push(Node{Kind: KeyValue})
+ start := b
- key, b, err := p.parseKey(b)
+ firstKey, b, err := p.parseKey(b)
if err != nil {
- return ref, nil, err
+ return 0, nil, err
}
- p.builder.AttachChild(ref, key)
-
- b = p.parseWhitespace(b)
+ if len(b) == 0 || b[0] != '=' {
+ return 0, nil, NewParserError(highlight1(b), "expected '=' after key")
+ }
+ b = skipWhitespace(b[1:])
- b, err = expect(']', b)
+ value, b, err := p.parseVal(b)
+ if err != nil {
+ return 0, nil, err
+ }
- return ref, b, err
+ p.at(root).child = value
+ p.at(value).next = firstKey
+ p.at(root).Raw = p.rangeFrom(start, b)
+ return root, b, nil
}
-func (p *Parser) parseKeyval(b []byte) (reference, []byte, error) {
- // keyval = key keyval-sep val
- ref := p.builder.Push(Node{
- Kind: KeyValue,
- })
+// parseKey parses a potentially dotted key. It consumes the whitespace
+// following the key, so that the caller can directly check for the next
+// expected character ('=', ']', ...). Returns the handle of the first Key
+// node; subsequent parts are chained via next.
+func (p *Parser) parseKey(b []byte) (int32, []byte, error) {
+ var first, last int32
+ for {
+ h, rest, err := p.parseSimpleKey(b)
+ if err != nil {
+ return 0, nil, err
+ }
+ if first == 0 {
+ first = h
+ } else {
+ p.at(last).next = h
+ }
+ last = h
- key, b, err := p.parseKey(b)
- if err != nil {
- return invalidReference, nil, err
+ b = skipWhitespace(rest)
+ if len(b) > 0 && b[0] == '.' {
+ b = skipWhitespace(b[1:])
+ continue
+ }
+ return first, b, nil
}
+}
- // keyval-sep = ws %x3D ws ; =
+func isUnquotedKeyChar(c byte) bool {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_'
+}
- b = p.parseWhitespace(b)
+// parseSimpleKey parses one key part: either a bare key or a quoted key.
+func (p *Parser) parseSimpleKey(b []byte) (int32, []byte, error) {
+ raw, value, rest, err := p.scanSimpleKey(b)
+ if err != nil {
+ return 0, nil, err
+ }
+ h := p.push(Node{Kind: Key, Raw: p.Range(raw), Data: value})
+ return h, rest, nil
+}
+// scanSimpleKey scans one key part (bare or quoted) without building an AST
+// node. It returns the raw bytes, the decoded key value, and the rest of the
+// input.
+func (p *Parser) scanSimpleKey(b []byte) (raw, value, rest []byte, err error) {
if len(b) == 0 {
- return invalidReference, nil, NewParserError(b, "expected = after a key, but the document ends there")
+ return nil, nil, nil, NewParserError(b, "expected key but reached end of input")
}
- b, err = expect('=', b)
- if err != nil {
- return invalidReference, nil, err
+ switch b[0] {
+ case '\'':
+ return p.parseLiteralString(b)
+ case '"':
+ return p.parseBasicString(b)
+ default:
+ i := 0
+ for i < len(b) && isUnquotedKeyChar(b[i]) {
+ i++
+ }
+ if i == 0 {
+ return nil, nil, nil, NewParserError(b[:1], "invalid character at start of key: %#U", b[0])
+ }
+ return b[:i], b[:i], b[i:], nil
}
+}
- b = p.parseWhitespace(b)
-
- valRef, b, err := p.parseVal(b)
- if err != nil {
- return ref, b, err
+// parseVal parses a TOML value and returns the handle to its node.
+func (p *Parser) parseVal(b []byte) (int32, []byte, error) {
+ if len(b) == 0 {
+ return 0, nil, NewParserError(b, "expected value, not end of input")
}
- p.builder.Chain(valRef, key)
- p.builder.AttachChild(ref, valRef)
-
- return ref, b, err
+ c := b[0]
+ switch {
+ case c == '"':
+ var raw, value, rest []byte
+ var err error
+ if len(b) > 2 && b[1] == '"' && b[2] == '"' {
+ raw, value, rest, err = p.parseMultilineBasicString(b)
+ } else {
+ raw, value, rest, err = p.parseBasicString(b)
+ }
+ if err != nil {
+ return 0, nil, err
+ }
+ h := p.push(Node{Kind: String, Raw: p.Range(raw), Data: value})
+ return h, rest, nil
+ case c == '\'':
+ var raw, value, rest []byte
+ var err error
+ if len(b) > 2 && b[1] == '\'' && b[2] == '\'' {
+ raw, value, rest, err = p.parseMultilineLiteralString(b)
+ } else {
+ raw, value, rest, err = p.parseLiteralString(b)
+ }
+ if err != nil {
+ return 0, nil, err
+ }
+ h := p.push(Node{Kind: String, Raw: p.Range(raw), Data: value})
+ return h, rest, nil
+ case c == 't':
+ return p.parseKeyword(b, "true", Bool)
+ case c == 'f':
+ return p.parseKeyword(b, "false", Bool)
+ case c == 'i':
+ return p.parseKeyword(b, "inf", Float)
+ case c == 'n':
+ return p.parseKeyword(b, "nan", Float)
+ case c == '[' || c == '{':
+ // Arrays and inline tables recurse back into parseVal for each of
+ // their elements. Bound that recursion so a document with millions of
+ // nested brackets or braces cannot overflow the goroutine stack.
+ if p.nesting >= maxValueNesting {
+ return 0, nil, NewParserError(b[:1], "arrays and inline tables are nested more than the maximum of %d levels deep", maxValueNesting)
+ }
+ p.nesting++
+ var h int32
+ var rest []byte
+ var err error
+ if c == '[' {
+ h, rest, err = p.parseValArray(b)
+ } else {
+ h, rest, err = p.parseInlineTable(b)
+ }
+ p.nesting--
+ return h, rest, err
+ case c == '+' || c == '-':
+ return p.parseIntOrFloat(b)
+ case c >= '0' && c <= '9':
+ if isDateTimeStart(b) {
+ return p.parseDateTime(b)
+ }
+ return p.parseIntOrFloat(b)
+ default:
+ return 0, nil, NewParserError(b[:1], "unexpected character %#U at start of value", c)
+ }
}
-//nolint:cyclop,funlen
-func (p *Parser) parseVal(b []byte) (reference, []byte, error) {
- // val = string / boolean / array / inline-table / date-time / float / integer
- ref := invalidReference
-
+// scanScalar scans a single scalar TOML value (string, integer, float,
+// boolean, or date/time) without building any AST node. It returns the kind of
+// the value, its raw bytes, its decoded value bytes (for strings: quotes
+// removed and escapes resolved; identical to raw for the other kinds), and the
+// rest of the input. Arrays and inline tables are not scalars and produce an
+// error: use parseValue for those.
+//
+// It is exposed to the root toml package through internal/parserbridge for the
+// fused generic-decode path; it is not part of the public API.
+func (p *Parser) scanScalar(b []byte) (kind Kind, raw, value, rest []byte, err error) {
if len(b) == 0 {
- return ref, nil, NewParserError(b, "expected value, not eof")
+ return Invalid, nil, nil, nil, NewParserError(b, "expected value, not end of input")
}
- var err error
c := b[0]
-
- switch c {
- case '"':
- var raw []byte
- var v []byte
- if scanFollowsMultilineBasicStringDelimiter(b) {
- raw, v, b, err = p.parseMultilineBasicString(b)
+ switch {
+ case c == '"':
+ if len(b) > 2 && b[1] == '"' && b[2] == '"' {
+ raw, value, rest, err = p.parseMultilineBasicString(b)
} else {
- raw, v, b, err = p.parseBasicString(b)
- }
-
- if err == nil {
- ref = p.builder.Push(Node{
- Kind: String,
- Raw: p.Range(raw),
- Data: v,
- })
+ raw, value, rest, err = p.parseBasicString(b)
}
-
- return ref, b, err
- case '\'':
- var raw []byte
- var v []byte
- if scanFollowsMultilineLiteralStringDelimiter(b) {
- raw, v, b, err = p.parseMultilineLiteralString(b)
+ return String, raw, value, rest, err
+ case c == '\'':
+ if len(b) > 2 && b[1] == '\'' && b[2] == '\'' {
+ raw, value, rest, err = p.parseMultilineLiteralString(b)
} else {
- raw, v, b, err = p.parseLiteralString(b)
+ raw, value, rest, err = p.parseLiteralString(b)
}
-
- if err == nil {
- ref = p.builder.Push(Node{
- Kind: String,
- Raw: p.Range(raw),
- Data: v,
- })
+ return String, raw, value, rest, err
+ case c == 't':
+ return scanKeyword(b, "true", Bool)
+ case c == 'f':
+ return scanKeyword(b, "false", Bool)
+ case c == 'i':
+ return scanKeyword(b, "inf", Float)
+ case c == 'n':
+ return scanKeyword(b, "nan", Float)
+ case c == '+' || c == '-':
+ return scanIntOrFloat(b)
+ case c >= '0' && c <= '9':
+ if isDateTimeStart(b) {
+ return scanDateTime(b)
}
+ return scanIntOrFloat(b)
+ default:
+ return Invalid, nil, nil, nil, NewParserError(b[:1], "unexpected character %#U at start of value", c)
+ }
+}
- return ref, b, err
- case 't':
- if !scanFollowsTrue(b) {
- return ref, nil, NewParserError(atmost(b, 4), "expected 'true'")
+// scanKey scans a potentially dotted key without building AST nodes,
+// appending the decoded value of each part to dst (pass dst[:0] to reuse a
+// buffer). It consumes the whitespace following the key, so the caller can
+// directly check for the next expected character ('=', ']', ...). It returns
+// the parts, the raw bytes spanning the whole key (from the first part to the
+// end of the last one, excluding trailing whitespace, usable as an error
+// highlight), the rest of the input, and any error.
+//
+// It is exposed to the root toml package through internal/parserbridge for the
+// fused generic-decode path; it is not part of the public API.
+func (p *Parser) scanKey(b []byte, dst [][]byte) (parts [][]byte, raw, rest []byte, err error) {
+ parts = dst
+ start := b
+ for {
+ _, value, r, err := p.scanSimpleKey(b)
+ if err != nil {
+ return nil, nil, nil, err
}
+ parts = append(parts, value)
- ref = p.builder.Push(Node{
- Kind: Bool,
- Data: b[:4],
- })
+ // r points just past the current part: the key spans from start to
+ // here, ignoring any whitespace that follows.
+ raw = start[:len(start)-len(r)]
- return ref, b[4:], nil
- case 'f':
- if !scanFollowsFalse(b) {
- return ref, nil, NewParserError(atmost(b, 5), "expected 'false'")
+ b = skipWhitespace(r)
+ if len(b) > 0 && b[0] == '.' {
+ b = skipWhitespace(b[1:])
+ continue
}
-
- ref = p.builder.Push(Node{
- Kind: Bool,
- Data: b[:5],
- })
-
- return ref, b[5:], nil
- case '[':
- return p.parseValArray(b)
- case '{':
- return p.parseInlineTable(b)
- default:
- return p.parseIntOrFloatOrDateTime(b)
+ return parts, raw, b, nil
}
}
-func atmost(b []byte, n int) []byte {
- if n >= len(b) {
- return b
+// parseValue parses a single TOML value, which may be an array or inline table,
+// into the parser's arena. It returns the root node of the value and the rest
+// of the input. It resets the arena, so any node returned by a previous call to
+// parseValue, Expression, or NextExpression is invalidated.
+//
+// It is exposed to the root toml package through internal/parserbridge for the
+// fused generic-decode path; it is not part of the public API.
+func (p *Parser) parseValue(b []byte) (*Node, []byte, error) {
+ p.nodes = p.nodes[:0]
+ h, rest, err := p.parseVal(b)
+ if err != nil {
+ return nil, nil, err
}
-
- return b[:n]
+ return &p.nodes[h-1], rest, nil
}
-func (p *Parser) parseLiteralString(b []byte) ([]byte, []byte, []byte, error) {
- v, rest, err := scanLiteralString(b)
+func (p *Parser) parseKeyword(b []byte, kw string, kind Kind) (int32, []byte, error) {
+ k, raw, _, rest, err := scanKeyword(b, kw, kind)
if err != nil {
- return nil, nil, nil, err
+ return 0, nil, err
}
-
- return v, v[1 : len(v)-1], rest, nil
+ h := p.push(Node{Kind: k, Raw: p.Range(raw), Data: raw})
+ return h, rest, nil
}
-func (p *Parser) parseInlineTable(b []byte) (reference, []byte, error) {
- // inline-table = inline-table-open [ inline-table-keyvals ] inline-table-close
- // inline-table-open = %x7B ws ; {
- // inline-table-close = ws %x7D ; }
- // inline-table-sep = ws %x2C ws ; , Comma
- // inline-table-keyvals = keyval [ inline-table-sep inline-table-keyvals ]
- parent := p.builder.Push(Node{
- Kind: InlineTable,
- Raw: p.Range(b[:1]),
- })
-
- first := true
-
- var child reference
+// scanKeyword scans a keyword value (true, false, inf, nan) without building
+// an AST node. raw and value are identical (the keyword bytes).
+func scanKeyword(b []byte, kw string, kind Kind) (Kind, []byte, []byte, []byte, error) {
+ if len(b) < len(kw) || string(b[:len(kw)]) != kw {
+ n := len(kw)
+ if len(b) < n {
+ n = len(b)
+ }
+ return Invalid, nil, nil, nil, NewParserError(b[:n], "expected keyword %q", kw)
+ }
+ return kind, b[:len(kw)], b[:len(kw)], b[len(kw):], nil
+}
+// parseValArray parses an array value. b starts at '['.
+func (p *Parser) parseValArray(b []byte) (int32, []byte, error) {
+ arr := p.push(Node{Kind: Array})
b = b[1:]
- var err error
+ var lastChild int32
+ appendChild := func(h int32) {
+ if lastChild == 0 {
+ p.at(arr).child = h
+ } else {
+ p.at(lastChild).next = h
+ }
+ lastChild = h
+ }
- for len(b) > 0 {
- previousB := b
- b = p.parseWhitespace(b)
+ // Comments inside the array are attached as follows: the first comment
+ // of a "run" (consecutive comments with no value in between) becomes a
+ // child of the array, interleaved with values; subsequent comments of the
+ // run are attached as children of the first one.
+ var runFirst, runLast int32
+ // afterValue is true when a value has been parsed and a comma (or the
+ // closing bracket) is expected before the next one.
+ afterValue := false
+ for {
+ b = skipWhitespace(b)
if len(b) == 0 {
- return parent, nil, NewParserError(previousB[:1], "inline table is incomplete")
- }
-
- if b[0] == '}' {
- break
+ return 0, nil, NewParserError(b, "array is incomplete")
}
- if !first {
- b, err = expect(',', b)
+ switch b[0] {
+ case ']':
+ return arr, b[1:], nil
+ case '\n':
+ b = b[1:]
+ continue
+ case '\r':
+ if len(b) > 1 && b[1] == '\n' {
+ b = b[2:]
+ continue
+ }
+ return 0, nil, NewParserError(b[:1], "expected newline but got %#U", b[0])
+ case '#':
+ comment, rest, err := scanComment(b)
if err != nil {
- return parent, nil, err
+ return 0, nil, err
}
- b = p.parseWhitespace(b)
- }
-
- var kv reference
-
- kv, b, err = p.parseKeyval(b)
- if err != nil {
- return parent, nil, err
- }
-
- if first {
- p.builder.AttachChild(parent, kv)
- } else {
- p.builder.Chain(child, kv)
+ if p.KeepComments {
+ h := p.push(Node{Kind: Comment, Raw: p.Range(comment), Data: comment})
+ switch {
+ case runFirst == 0:
+ appendChild(h)
+ runFirst = h
+ case runLast == runFirst:
+ p.at(runFirst).child = h
+ default:
+ p.at(runLast).next = h
+ }
+ runLast = h
+ }
+ b = rest
+ continue
+ case ',':
+ if !afterValue {
+ return 0, nil, NewParserError(b[:1], "expected value but got %#U", b[0])
+ }
+ afterValue = false
+ b = b[1:]
+ continue
+ default:
+ if afterValue {
+ return 0, nil, NewParserError(b[:1], "expected ',' or ']' after array value")
+ }
+ h, rest, err := p.parseVal(b)
+ if err != nil {
+ return 0, nil, err
+ }
+ appendChild(h)
+ afterValue = true
+ runFirst, runLast = 0, 0
+ b = rest
+ continue
}
- child = kv
-
- first = false
}
-
- rest, err := expect('}', b)
-
- return parent, rest, err
}
-//nolint:funlen,cyclop
-func (p *Parser) parseValArray(b []byte) (reference, []byte, error) {
- // array = array-open [ array-values ] ws-comment-newline array-close
- // array-open = %x5B ; [
- // array-close = %x5D ; ]
- // array-values = ws-comment-newline val ws-comment-newline array-sep array-values
- // array-values =/ ws-comment-newline val ws-comment-newline [ array-sep ]
- // array-sep = %x2C ; , Comma
- // ws-comment-newline = *( wschar / [ comment ] newline )
- arrayStart := b
+// parseInlineTable parses an inline table value. b starts at '{'.
+//
+// Per TOML v1.1.0, inline tables may span multiple lines (whitespace,
+// comments and newlines are allowed between elements) and may contain a
+// trailing comma.
+func (p *Parser) parseInlineTable(b []byte) (int32, []byte, error) {
+ tbl := p.push(Node{Kind: InlineTable, Raw: p.Range(b[:1])})
b = b[1:]
- parent := p.builder.Push(Node{
- Kind: Array,
- })
-
- // First indicates whether the parser is looking for the first element
- // (non-comment) of the array.
- first := true
-
- lastChild := invalidReference
-
- addChild := func(valueRef reference) {
- if lastChild == invalidReference {
- p.builder.AttachChild(parent, valueRef)
+ var lastChild int32
+ appendChild := func(h int32) {
+ if lastChild == 0 {
+ p.at(tbl).child = h
} else {
- p.builder.Chain(lastChild, valueRef)
+ p.at(lastChild).next = h
}
- lastChild = valueRef
+ lastChild = h
}
- var err error
- for len(b) > 0 {
- cref := invalidReference
- cref, b, err = p.parseOptionalWhitespaceCommentNewline(b)
- if err != nil {
- return parent, nil, err
- }
-
- if cref != invalidReference {
- addChild(cref)
- }
+ // Comments are attached as in arrays: the first comment of a "run"
+ // (consecutive comments with no key-value in between) becomes a child of
+ // the table, interleaved with key-values; subsequent comments of the run
+ // hang off the first one.
+ var runFirst, runLast int32
+ // afterValue is true when a key-value has been parsed and a comma (or the
+ // closing brace) is expected before the next one.
+ afterValue := false
+ for {
+ b = skipWhitespace(b)
if len(b) == 0 {
- return parent, nil, NewParserError(arrayStart[:1], "array is incomplete")
- }
-
- if b[0] == ']' {
- break
+ return 0, nil, NewParserError(b, "inline table is incomplete")
}
- if b[0] == ',' {
- if first {
- return parent, nil, NewParserError(b[0:1], "array cannot start with comma")
- }
+ switch b[0] {
+ case '}':
+ return tbl, b[1:], nil
+ case '\n':
b = b[1:]
-
- cref, b, err = p.parseOptionalWhitespaceCommentNewline(b)
+ continue
+ case '\r':
+ if len(b) > 1 && b[1] == '\n' {
+ b = b[2:]
+ continue
+ }
+ return 0, nil, NewParserError(b[:1], "expected newline but got %#U", b[0])
+ case '#':
+ comment, rest, err := scanComment(b)
if err != nil {
- return parent, nil, err
+ return 0, nil, err
}
- if cref != invalidReference {
- addChild(cref)
+ if p.KeepComments {
+ h := p.push(Node{Kind: Comment, Raw: p.Range(comment), Data: comment})
+ switch {
+ case runFirst == 0:
+ appendChild(h)
+ runFirst = h
+ case runLast == runFirst:
+ p.at(runFirst).child = h
+ default:
+ p.at(runLast).next = h
+ }
+ runLast = h
}
- } else if !first {
- return parent, nil, NewParserError(b[0:1], "array elements must be separated by commas")
- }
-
- // TOML allows trailing commas in arrays.
- if len(b) > 0 && b[0] == ']' {
- break
- }
-
- var valueRef reference
- valueRef, b, err = p.parseVal(b)
- if err != nil {
- return parent, nil, err
+ b = rest
+ continue
+ case ',':
+ if !afterValue {
+ return 0, nil, NewParserError(b[:1], "unexpected comma in inline table")
+ }
+ afterValue = false
+ b = b[1:]
+ continue
+ default:
+ if afterValue {
+ return 0, nil, NewParserError(b[:1], "expected ',' or '}' after inline table key-value")
+ }
+ h, rest, err := p.parseKeyval(b)
+ if err != nil {
+ return 0, nil, err
+ }
+ appendChild(h)
+ afterValue = true
+ runFirst, runLast = 0, 0
+ b = rest
+ continue
}
+ }
+}
- addChild(valueRef)
+func isDigit(c byte) bool {
+ return c >= '0' && c <= '9'
+}
- cref, b, err = p.parseOptionalWhitespaceCommentNewline(b)
- if err != nil {
- return parent, nil, err
- }
- if cref != invalidReference {
- addChild(cref)
- }
+func isHexDigit(c byte) bool {
+ return isDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')
+}
- first = false
+// isDateTimeStart reports whether b looks like the start of a date or time
+// value instead of a number. Values starting with two digits followed by a
+// colon are times; values starting with four digits followed by a dash are
+// dates.
+func isDateTimeStart(b []byte) bool {
+ if len(b) >= 3 && isDigit(b[1]) && b[2] == ':' {
+ return true
}
-
- rest, err := expect(']', b)
-
- return parent, rest, err
+ if len(b) >= 5 && isDigit(b[1]) && isDigit(b[2]) && isDigit(b[3]) && b[4] == '-' {
+ return true
+ }
+ return false
}
-func (p *Parser) parseOptionalWhitespaceCommentNewline(b []byte) (reference, []byte, error) {
- rootCommentRef := invalidReference
- latestCommentRef := invalidReference
+// expectDigits checks that the n first bytes of b are digits.
+// parseDateTime parses date and/or time values. b starts with a digit.
+//
+// The parser is lenient: it scans the characters that can be part of a date
+// and/or time value to delimit and classify the token, but leaves the
+// validation of its contents to the document consumer. This keeps the value
+// in one piece, so that errors about its content can point at the right
+// place.
+func (p *Parser) parseDateTime(b []byte) (int32, []byte, error) {
+ kind, raw, _, rest, err := scanDateTime(b)
+ if err != nil {
+ return 0, nil, err
+ }
+ h := p.push(Node{Kind: kind, Raw: p.Range(raw), Data: raw})
+ return h, rest, nil
+}
- addComment := func(ref reference) {
- if rootCommentRef == invalidReference {
- rootCommentRef = ref
- } else if latestCommentRef == invalidReference {
- p.builder.AttachChild(rootCommentRef, ref)
- latestCommentRef = ref
- } else {
- p.builder.Chain(latestCommentRef, ref)
- latestCommentRef = ref
+// scanDateTime classifies and delimits a date/time value without building an
+// AST node. raw and value are identical (the token bytes).
+func scanDateTime(b []byte) (Kind, []byte, []byte, []byte, error) {
+ // Greedily scan the characters that may compose a date/time value. A
+ // space is part of the value only when it serves as the delimiter
+ // between the date and the time, which is approximated by requiring a
+ // digit right after it.
+ i := 0
+ delim := -1
+ for i < len(b) {
+ c := b[i]
+ if isDigit(c) || c == ':' || c == '-' || c == '+' || c == '.' || c == 'Z' || c == 'z' {
+ i++
+ continue
+ }
+ if c == 'T' || c == 't' || (c == ' ' && i+1 < len(b) && isDigit(b[i+1])) {
+ if delim < 0 {
+ delim = i
+ }
+ i++
+ continue
}
+ break
}
+ tok := b[:i]
- for len(b) > 0 {
- var err error
- b = p.parseWhitespace(b)
+ var kind Kind
+ switch {
+ case tok[2] == ':':
+ kind = LocalTime
+ case delim < 0:
+ kind = LocalDate
+ case bytes.ContainsAny(tok[delim+1:], "Zz+-"):
+ kind = DateTime
+ default:
+ kind = LocalDateTime
+ }
- if len(b) > 0 && b[0] == '#' {
- var ref reference
- ref, b, err = p.parseComment(b)
- if err != nil {
- return invalidReference, nil, err
- }
- if ref != invalidReference {
- addComment(ref)
- }
- }
+ return kind, tok, tok, b[i:], nil
+}
- if len(b) == 0 {
- break
+// scanDigitsWithUnderscores scans a run of digits potentially separated by
+// underscores. b starts right after the first digit of the run. isInRange
+// selects the kind of digits. Returns the index after the run.
+func scanDigitsWithUnderscores(b []byte, i int, isInRange func(byte) bool) (int, error) {
+ for i < len(b) {
+ c := b[i]
+ if isInRange(c) {
+ i++
+ continue
}
-
- if b[0] == '\n' || b[0] == '\r' {
- b, err = p.parseNewline(b)
- if err != nil {
- return invalidReference, nil, err
+ if c == '_' {
+ if i+1 >= len(b) || !isInRange(b[i+1]) {
+ end := i + 2
+ if end > len(b) {
+ end = len(b)
+ }
+ return 0, NewParserError(b[i:end], "number must have at least one digit between underscores")
}
- } else {
- break
+ i += 2
+ continue
}
+ break
}
-
- return rootCommentRef, b, nil
+ return i, nil
}
-func (p *Parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, []byte, error) {
- token, rest, err := scanMultilineLiteralString(b)
+// parseIntOrFloat parses integer and float values, including the special
+// values inf and nan with an optional sign.
+func (p *Parser) parseIntOrFloat(b []byte) (int32, []byte, error) {
+ kind, raw, _, rest, err := scanIntOrFloat(b)
if err != nil {
- return nil, nil, nil, err
+ return 0, nil, err
}
+ h := p.push(Node{Kind: kind, Raw: p.Range(raw), Data: raw})
+ return h, rest, nil
+}
- i := 3
-
- // skip the immediate new line
- if token[i] == '\n' {
+// scanIntOrFloat delimits and classifies an integer or float value (including
+// the special floats inf and nan with an optional sign) without building an
+// AST node. raw and value are identical (the token bytes).
+func scanIntOrFloat(b []byte) (Kind, []byte, []byte, []byte, error) {
+ i := 0
+ if b[i] == '+' || b[i] == '-' {
i++
- } else if token[i] == '\r' && token[i+1] == '\n' {
- i += 2
+ }
+ if i >= len(b) {
+ return Invalid, nil, nil, nil, NewParserError(b, "expected number after sign")
}
- return token, token[i : len(token)-3], rest, err
-}
+ // special floats
+ if b[i] == 'i' || b[i] == 'n' {
+ kw := "inf"
+ if b[i] == 'n' {
+ kw = "nan"
+ }
+ if len(b) < i+3 || string(b[i:i+3]) != kw {
+ return Invalid, nil, nil, nil, NewParserError(b[i:i+1], "expected %q", kw)
+ }
+ i += 3
+ return Float, b[:i], b[:i], b[i:], nil
+ }
-//nolint:funlen,gocognit,cyclop
-func (p *Parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, error) {
- // ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
- // ml-basic-string-delim
- // ml-basic-string-delim = 3quotation-mark
- // ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ]
- //
- // mlb-content = mlb-char / newline / mlb-escaped-nl
- // mlb-char = mlb-unescaped / escaped
- // mlb-quotes = 1*2quotation-mark
- // mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
- // mlb-escaped-nl = escape ws newline *( wschar / newline )
- token, escaped, rest, err := scanMultilineBasicString(b)
+ if !isDigit(b[i]) {
+ return Invalid, nil, nil, nil, NewParserError(b[i:i+1], "expected digit but got %#U", b[i])
+ }
+
+ // radix prefixes
+ if b[i] == '0' && i+1 < len(b) && (b[i+1] == 'x' || b[i+1] == 'o' || b[i+1] == 'b') {
+ if i != 0 {
+ return Invalid, nil, nil, nil, NewParserError(b[:2], "sign is not allowed on numbers with a radix prefix")
+ }
+ var isInRange func(byte) bool
+ switch b[1] {
+ case 'x':
+ isInRange = isHexDigit
+ case 'o':
+ isInRange = func(c byte) bool { return c >= '0' && c <= '7' }
+ case 'b':
+ isInRange = func(c byte) bool { return c == '0' || c == '1' }
+ }
+ i = 2
+ if i >= len(b) || !isInRange(b[i]) {
+ return Invalid, nil, nil, nil, NewParserError(b[:2], "radix prefix must be followed by at least one digit")
+ }
+ i++
+ var err error
+ i, err = scanDigitsWithUnderscores(b, i, isInRange)
+ if err != nil {
+ return Invalid, nil, nil, nil, err
+ }
+ return Integer, b[:i], b[:i], b[i:], nil
+ }
+
+ // decimal integer part
+ leadingZero := b[i] == '0'
+ digitsStart := i
+ i++
+ var err error
+ i, err = scanDigitsWithUnderscores(b, i, isDigit)
if err != nil {
- return nil, nil, nil, err
+ return Invalid, nil, nil, nil, err
+ }
+ if leadingZero && i > digitsStart+1 {
+ return Invalid, nil, nil, nil, NewParserError(b[digitsStart:digitsStart+2], "integers cannot have leading zeroes")
}
- i := 3
+ kind := Integer
- // skip the immediate new line
- if token[i] == '\n' {
+ // fractional part
+ if i < len(b) && b[i] == '.' {
i++
- } else if token[i] == '\r' && token[i+1] == '\n' {
- i += 2
+ if i >= len(b) || !isDigit(b[i]) {
+ return Invalid, nil, nil, nil, NewParserError(highlight1(b[i:]), "decimal point must be followed by a digit")
+ }
+ i++
+ i, err = scanDigitsWithUnderscores(b, i, isDigit)
+ if err != nil {
+ return Invalid, nil, nil, nil, err
+ }
+ kind = Float
}
- // fast path
- startIdx := i
- endIdx := len(token) - len(`"""`)
+ // exponent
+ if i < len(b) && (b[i] == 'e' || b[i] == 'E') {
+ i++
+ if i < len(b) && (b[i] == '+' || b[i] == '-') {
+ i++
+ }
+ if i >= len(b) || !isDigit(b[i]) {
+ return Invalid, nil, nil, nil, NewParserError(highlight1(b[i:]), "exponent must contain at least one digit")
+ }
+ i++
+ i, err = scanDigitsWithUnderscores(b, i, isDigit)
+ if err != nil {
+ return Invalid, nil, nil, nil, err
+ }
+ kind = Float
+ }
- if !escaped {
- str := token[startIdx:endIdx]
- verr := characters.Utf8TomlValidAlreadyEscaped(str)
- if verr.Zero() {
- return token, str, rest, nil
+ // A letter right after the number means it was meant to be a string that
+ // was left unquoted (e.g. "20s"). Report that instead of the misleading
+ // "expected newline" raised later (issue #413).
+ if i < len(b) {
+ if c := b[i]; (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') {
+ return Invalid, nil, nil, nil, NewParserError(b[i:i+1], "strings must be quoted")
}
- return nil, nil, nil, NewParserError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
}
- var builder bytes.Buffer
+ return kind, b[:i], b[:i], b[i:], nil
+}
- // The scanner ensures that the token starts and ends with quotes and that
- // escapes are balanced.
- for i < len(token)-3 {
- c := token[i]
+// highlight1 returns a 1-byte highlight at the start of b, or b itself if it
+// is empty.
+func highlight1(b []byte) []byte {
+ if len(b) > 0 {
+ return b[:1]
+ }
+ return b
+}
- //nolint:nestif
- if c == '\\' {
- // When the last non-whitespace character on a line is an unescaped \,
- // it will be trimmed along with all whitespace (including newlines) up
- // to the next non-whitespace character or closing delimiter.
+func skipWhitespace(b []byte) []byte {
+ for len(b) > 0 && (b[0] == ' ' || b[0] == '\t') {
+ b = b[1:]
+ }
+ return b
+}
- isLastNonWhitespaceOnLine := false
- j := 1
- findEOLLoop:
- for ; j < len(token)-3-i; j++ {
- switch token[i+j] {
- case ' ', '\t':
- continue
- case '\r':
- if token[i+j+1] == '\n' {
- continue
- }
- case '\n':
- isLastNonWhitespaceOnLine = true
- }
- break findEOLLoop
- }
- if isLastNonWhitespaceOnLine {
- i += j
- for ; i < len(token)-3; i++ {
- c := token[i]
- if !(c == '\n' || c == '\r' || c == ' ' || c == '\t') {
- i--
- break
- }
- }
- i++
- continue
- }
+// Word-at-a-time byte scanning helpers. These detect, within an 8-byte word,
+// the presence of bytes that need special handling, so that runs of plain
+// ASCII characters can be skipped 8 bytes at a time.
+const (
+ lsb = 0x0101010101010101
+ msb = 0x8080808080808080
+)
- // handle escaping
- i++
- c = token[i]
+// hasByteBelow reports whether any byte of the word x is strictly below n.
+// Only meaningful when combined with a check that no byte has its high bit
+// set.
+func hasByteBelow(x uint64, n uint64) uint64 {
+ return (x - n*lsb) & ^x & msb
+}
- switch c {
- case '"', '\\':
- builder.WriteByte(c)
- case 'b':
- builder.WriteByte('\b')
- case 'f':
- builder.WriteByte('\f')
- case 'n':
- builder.WriteByte('\n')
- case 'r':
- builder.WriteByte('\r')
- case 't':
- builder.WriteByte('\t')
- case 'e':
- builder.WriteByte(0x1B)
- case 'u':
- x, err := hexToRune(atmost(token[i+1:], 4), 4)
- if err != nil {
- return nil, nil, nil, err
- }
- builder.WriteRune(x)
- i += 4
- case 'U':
- x, err := hexToRune(atmost(token[i+1:], 8), 8)
- if err != nil {
- return nil, nil, nil, err
- }
+// hasByteEqual reports whether any byte of the word x equals c. Only
+// meaningful for bytes without their high bit set.
+func hasByteEqual(x uint64, c uint64) uint64 {
+ y := x ^ (c * lsb)
+ return (y - lsb) & ^y & msb
+}
- builder.WriteRune(x)
- i += 8
- default:
- return nil, nil, nil, NewParserError(token[i:i+1], "invalid escaped character %#U", c)
+// scanComment parses a comment, starting at the '#' character. It returns the
+// comment bytes (including '#', excluding the line ending) and the rest of
+// the input.
+func scanComment(b []byte) ([]byte, []byte, error) {
+ i := 1
+ for i < len(b) {
+ // Fast path: skip 8 bytes at a time as long as they are all plain
+ // printable ASCII.
+ for i+8 <= len(b) {
+ x := binary.LittleEndian.Uint64(b[i:])
+ if (x&msb)|hasByteBelow(x, 0x20)|hasByteEqual(x, 0x7f) != 0 {
+ break
+ }
+ i += 8
+ }
+ if i >= len(b) {
+ break
+ }
+
+ c := b[i]
+ if c >= 0x80 {
+ var ok bool
+ i, ok = scanUtf8Run(b, i)
+ if !ok {
+ return nil, nil, NewParserError(b[i:i+1], "invalid UTF-8 character in comment")
}
+ continue
+ }
+ switch {
+ case c >= 0x20 && c < 0x7f:
i++
- } else {
- size := characters.Utf8ValidNext(token[i:])
- if size == 0 {
- return nil, nil, nil, NewParserError(token[i:i+1], "invalid character %#U", c)
+ case c == '\n':
+ return b[:i], b[i:], nil
+ case c == '\r':
+ if i+1 < len(b) && b[i+1] == '\n' {
+ return b[:i], b[i:], nil
}
- builder.Write(token[i : i+size])
- i += size
+ return nil, nil, NewParserError(b[i:i+1], "carriage returns are not allowed in comments")
+ case c == '\t':
+ i++
+ default:
+ return nil, nil, NewParserError(b[i:i+1], "control characters are not allowed in comments")
}
}
-
- return token, builder.Bytes(), rest, nil
+ return b[:i], b[i:], nil
}
-func (p *Parser) parseKey(b []byte) (reference, []byte, error) {
- // key = simple-key / dotted-key
- // simple-key = quoted-key / unquoted-key
- //
- // unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _
- // quoted-key = basic-string / literal-string
- // dotted-key = simple-key 1*( dot-sep simple-key )
- //
- // dot-sep = ws %x2E ws ; . Period
- raw, key, b, err := p.parseSimpleKey(b)
- if err != nil {
- return invalidReference, nil, err
- }
-
- ref := p.builder.Push(Node{
- Kind: Key,
- Raw: p.Range(raw),
- Data: key,
- })
-
+// parseLiteralString parses a single-line literal string, starting at the
+// opening quote. Returns the raw bytes (with quotes), the string value
+// (without quotes) and the rest of the input.
+func (p *Parser) parseLiteralString(b []byte) ([]byte, []byte, []byte, error) {
+ i := 1
for {
- b = p.parseWhitespace(b)
- if len(b) > 0 && b[0] == '.' {
- b = p.parseWhitespace(b[1:])
-
- raw, key, b, err = p.parseSimpleKey(b)
- if err != nil {
- return ref, nil, err
+ // Fast path over plain ASCII.
+ for i+8 <= len(b) {
+ x := binary.LittleEndian.Uint64(b[i:])
+ if (x&msb)|hasByteBelow(x, 0x20)|hasByteEqual(x, '\'')|hasByteEqual(x, 0x7f) != 0 {
+ break
}
+ i += 8
+ }
+ if i >= len(b) {
+ return nil, nil, nil, NewParserError(b[len(b):], "unterminated literal string")
+ }
- p.builder.PushAndChain(Node{
- Kind: Key,
- Raw: p.Range(raw),
- Data: key,
- })
- } else {
- break
+ c := b[i]
+ switch {
+ case c == '\'':
+ return b[:i+1], b[1:i], b[i+1:], nil
+ case c >= 0x20 && c < 0x7f:
+ i++
+ case c == '\t':
+ i++
+ case c == '\n' || c == '\r':
+ return nil, nil, nil, NewParserError(b[i:i+1], "literal strings cannot have new lines")
+ case c < 0x80:
+ return nil, nil, nil, NewParserError(b[i:i+1], "literal strings cannot have control characters")
+ default:
+ var ok bool
+ i, ok = scanUtf8Run(b, i)
+ if !ok {
+ return nil, nil, nil, NewParserError(b[i:i+1], "invalid UTF-8 character in literal string")
+ }
}
}
-
- return ref, b, nil
}
-func (p *Parser) parseSimpleKey(b []byte) (raw, key, rest []byte, err error) {
- if len(b) == 0 {
- return nil, nil, nil, NewParserError(b, "expected key but found none")
+// parseMultilineLiteralString parses a multi-line literal string, starting at
+// the opening triple quote.
+func (p *Parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, []byte, error) {
+ i := 3
+ // trim the newline right after the opening delimiter
+ if i < len(b) && b[i] == '\n' {
+ i++
+ } else if i+1 < len(b) && b[i] == '\r' && b[i+1] == '\n' {
+ i += 2
}
+ contentStart := i
- // simple-key = quoted-key / unquoted-key
- // unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _
- // quoted-key = basic-string / literal-string
- switch {
- case b[0] == '\'':
- return p.parseLiteralString(b)
- case b[0] == '"':
- return p.parseBasicString(b)
- case isUnquotedKeyChar(b[0]):
- key, rest = scanUnquotedKey(b)
- return key, key, rest, nil
- default:
- return nil, nil, nil, NewParserError(b[0:1], "invalid character at start of key: %c", b[0])
+ for i < len(b) {
+ c := b[i]
+ switch {
+ case c == '\'':
+ // count consecutive quotes
+ j := i
+ for j < len(b) && b[j] == '\'' {
+ j++
+ }
+ n := j - i
+ if n >= 3 {
+ if n > 5 {
+ return nil, nil, nil, NewParserError(b[i:j], "too many quotes at the end of a multiline literal string")
+ }
+ // n-3 quotes belong to the content; the last 3 close the
+ // string.
+ contentEnd := i + n - 3
+ return b[:j], b[contentStart:contentEnd], b[j:], nil
+ }
+ i = j
+ case c >= 0x20 && c < 0x7f:
+ i++
+ case c == '\t' || c == '\n':
+ i++
+ case c == '\r':
+ if i+1 < len(b) && b[i+1] == '\n' {
+ i += 2
+ continue
+ }
+ return nil, nil, nil, NewParserError(b[i:i+1], "carriage returns must be followed by a newline character")
+ case c < 0x80:
+ return nil, nil, nil, NewParserError(b[i:i+1], "multiline literal strings cannot have control characters")
+ default:
+ var ok bool
+ i, ok = scanUtf8Run(b, i)
+ if !ok {
+ return nil, nil, nil, NewParserError(b[i:i+1], "invalid UTF-8 character in multiline literal string")
+ }
+ }
}
+ return nil, nil, nil, NewParserError(b[len(b):], "multiline literal string not terminated by '''")
}
-//nolint:funlen,cyclop
+// parseBasicString parses a single-line basic string, starting at the opening
+// quote. The value is a subslice of the input if the string contains no
+// escape sequence, or a new allocation otherwise.
func (p *Parser) parseBasicString(b []byte) ([]byte, []byte, []byte, error) {
- // basic-string = quotation-mark *basic-char quotation-mark
- // quotation-mark = %x22 ; "
- // basic-char = basic-unescaped / escaped
- // basic-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
- // escaped = escape escape-seq-char
- // escape-seq-char = %x22 ; " quotation mark U+0022
- // escape-seq-char =/ %x5C ; \ reverse solidus U+005C
- // escape-seq-char =/ %x62 ; b backspace U+0008
- // escape-seq-char =/ %x66 ; f form feed U+000C
- // escape-seq-char =/ %x6E ; n line feed U+000A
- // escape-seq-char =/ %x72 ; r carriage return U+000D
- // escape-seq-char =/ %x74 ; t tab U+0009
- // escape-seq-char =/ %x75 4HEXDIG ; uXXXX U+XXXX
- // escape-seq-char =/ %x55 8HEXDIG ; UXXXXXXXX U+XXXXXXXX
- token, escaped, rest, err := scanBasicString(b)
- if err != nil {
- return nil, nil, nil, err
- }
-
- startIdx := len(`"`)
- endIdx := len(token) - len(`"`)
+ i := 1
+ // First pass: handle strings without escape sequences without allocating.
+ for {
+ for i+8 <= len(b) {
+ x := binary.LittleEndian.Uint64(b[i:])
+ if (x&msb)|hasByteBelow(x, 0x20)|hasByteEqual(x, '"')|hasByteEqual(x, '\\')|hasByteEqual(x, 0x7f) != 0 {
+ break
+ }
+ i += 8
+ }
+ if i >= len(b) {
+ return nil, nil, nil, NewParserError(b[len(b):], "unterminated basic string")
+ }
- // Fast path. If there is no escape sequence, the string should just be
- // an UTF-8 encoded string, which is the same as Go. In that case,
- // validate the string and return a direct reference to the buffer.
- if !escaped {
- str := token[startIdx:endIdx]
- verr := characters.Utf8TomlValidAlreadyEscaped(str)
- if verr.Zero() {
- return token, str, rest, nil
+ c := b[i]
+ switch {
+ case c == '"':
+ return b[:i+1], b[1:i], b[i+1:], nil
+ case c == '\\':
+ // switch to the escape-aware parser, copying what has been
+ // scanned so far
+ return p.parseBasicStringEscaped(b, i)
+ case c >= 0x20 && c < 0x7f:
+ i++
+ case c == '\t':
+ i++
+ case c == '\n' || c == '\r':
+ return nil, nil, nil, NewParserError(b[i:i+1], "basic strings cannot have new lines")
+ case c < 0x80:
+ return nil, nil, nil, NewParserError(b[i:i+1], "basic strings cannot have control characters")
+ default:
+ var ok bool
+ i, ok = scanUtf8Run(b, i)
+ if !ok {
+ return nil, nil, nil, NewParserError(b[i:i+1], "invalid UTF-8 character in basic string")
+ }
}
- return nil, nil, nil, NewParserError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
}
+}
- i := startIdx
-
- var builder bytes.Buffer
-
- // The scanner ensures that the token starts and ends with quotes and that
- // escapes are balanced.
- for i < len(token)-1 {
- c := token[i]
- if c == '\\' {
+// findBasicStringEnd returns the index of the quote closing a basic string,
+// or -1 if the string is not terminated. i is the index of the first
+// character after the opening quote. It does not validate the content: it
+// only skips over escape sequences so that escaped quotes do not terminate
+// the string.
+func findBasicStringEnd(b []byte, i int) int {
+ for i < len(b) {
+ switch b[i] {
+ case '"':
+ return i
+ case '\\':
+ i += 2
+ default:
i++
- c = token[i]
-
- switch c {
- case '"', '\\':
- builder.WriteByte(c)
- case 'b':
- builder.WriteByte('\b')
- case 'f':
- builder.WriteByte('\f')
- case 'n':
- builder.WriteByte('\n')
- case 'r':
- builder.WriteByte('\r')
- case 't':
- builder.WriteByte('\t')
- case 'e':
- builder.WriteByte(0x1B)
- case 'u':
- x, err := hexToRune(token[i+1:len(token)-1], 4)
- if err != nil {
- return nil, nil, nil, err
- }
+ }
+ }
+ return -1
+}
- builder.WriteRune(x)
- i += 4
- case 'U':
- x, err := hexToRune(token[i+1:len(token)-1], 8)
- if err != nil {
- return nil, nil, nil, err
- }
+// parseBasicStringEscaped continues parsing a basic string that contains
+// escape sequences. i is the index of the first backslash.
+func (p *Parser) parseBasicStringEscaped(b []byte, i int) ([]byte, []byte, []byte, error) {
+ // Escape sequences only ever shrink, so the content length before
+ // unescaping is enough to never reallocate.
+ bufCap := len(b) - 1
+ if end := findBasicStringEnd(b, i); end >= 0 {
+ bufCap = end - 1
+ }
+ buf := make([]byte, i-1, bufCap)
+ copy(buf, b[1:i])
- builder.WriteRune(x)
- i += 8
- default:
- return nil, nil, nil, NewParserError(token[i:i+1], "invalid escaped character %#U", c)
+ for i < len(b) {
+ c := b[i]
+ switch {
+ case c == '"':
+ return b[:i+1], buf, b[i+1:], nil
+ case c == '\\':
+ i++
+ if i >= len(b) {
+ return nil, nil, nil, NewParserError(b[i-1:], `need a character after \`)
}
+ var err error
+ buf, i, err = unescape(buf, b, i)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ case c >= 0x20 && c < 0x7f:
+ buf = append(buf, c)
i++
- } else {
- size := characters.Utf8ValidNext(token[i:])
- if size == 0 {
- return nil, nil, nil, NewParserError(token[i:i+1], "invalid character %#U", c)
+ case c == '\t':
+ buf = append(buf, c)
+ i++
+ case c == '\n' || c == '\r':
+ return nil, nil, nil, NewParserError(b[i:i+1], "basic strings cannot have new lines")
+ case c < 0x80:
+ return nil, nil, nil, NewParserError(b[i:i+1], "basic strings cannot have control characters")
+ default:
+ j, ok := scanUtf8Run(b, i)
+ if !ok {
+ return nil, nil, nil, NewParserError(b[i:i+1], "invalid UTF-8 character in basic string")
}
- builder.Write(token[i : i+size])
- i += size
+ buf = append(buf, b[i:j]...)
+ i = j
}
}
-
- return token, builder.Bytes(), rest, nil
+ return nil, nil, nil, NewParserError(b[len(b):], "unterminated basic string")
}
-func hexToRune(b []byte, length int) (rune, error) {
- if len(b) < length {
- return -1, NewParserError(b, "unicode point needs %d character, not %d", length, len(b))
+// unescape processes one escape sequence. i is the index of the character
+// right after the backslash. It returns the updated buffer and index.
+func unescape(buf []byte, b []byte, i int) ([]byte, int, error) {
+ c := b[i]
+ switch c {
+ case '"':
+ return append(buf, '"'), i + 1, nil
+ case '\\':
+ return append(buf, '\\'), i + 1, nil
+ case 'b':
+ return append(buf, '\b'), i + 1, nil
+ case 'f':
+ return append(buf, '\f'), i + 1, nil
+ case 'n':
+ return append(buf, '\n'), i + 1, nil
+ case 'r':
+ return append(buf, '\r'), i + 1, nil
+ case 't':
+ return append(buf, '\t'), i + 1, nil
+ case 'e':
+ // TOML v1.1.0: \e is the escape character (U+001B).
+ return append(buf, 0x1B), i + 1, nil
+ case 'x':
+ // TOML v1.1.0: \xHH is a two-digit hexadecimal code point.
+ return unescapeUnicode(buf, b, i+1, 2)
+ case 'u':
+ return unescapeUnicode(buf, b, i+1, 4)
+ case 'U':
+ return unescapeUnicode(buf, b, i+1, 8)
+ default:
+ return nil, 0, NewParserError(b[i-1:i+1], "invalid escape character %#U", c)
}
- b = b[:length]
+}
+// unescapeUnicode handles \uXXXX and \UXXXXXXXX escape sequences. i is the
+// index of the first hex digit.
+func unescapeUnicode(buf []byte, b []byte, i int, n int) ([]byte, int, error) {
+ if i+n > len(b) {
+ return nil, 0, NewParserError(b[i-2:], "unicode escape sequence is too short")
+ }
var r uint32
- for i, c := range b {
- d := uint32(0)
+ for k := 0; k < n; k++ {
+ c := b[i+k]
+ var d uint32
switch {
- case '0' <= c && c <= '9':
+ case c >= '0' && c <= '9':
d = uint32(c - '0')
- case 'a' <= c && c <= 'f':
- d = uint32(c - 'a' + 10)
- case 'A' <= c && c <= 'F':
- d = uint32(c - 'A' + 10)
+ case c >= 'a' && c <= 'f':
+ d = uint32(c-'a') + 10
+ case c >= 'A' && c <= 'F':
+ d = uint32(c-'A') + 10
default:
- return -1, NewParserError(b[i:i+1], "non-hex character")
+ return nil, 0, NewParserError(b[i+k:i+k+1], "invalid hexadecimal digit in unicode escape sequence")
}
- r = r*16 + d
+ r = r<<4 | d
}
-
- if r > unicode.MaxRune || 0xD800 <= r && r < 0xE000 {
- return -1, NewParserError(b, "escape sequence is invalid Unicode code point")
+ if r > utf8.MaxRune || (r >= 0xD800 && r <= 0xDFFF) {
+ return nil, 0, NewParserError(b[i-2:i+n], "escape sequence is not a valid unicode code point")
}
-
- return rune(r), nil
-}
-
-func (p *Parser) parseWhitespace(b []byte) []byte {
- // ws = *wschar
- // wschar = %x20 ; Space
- // wschar =/ %x09 ; Horizontal tab
- _, rest := scanWhitespace(b)
-
- return rest
+ return utf8.AppendRune(buf, rune(r)), i + n, nil
}
-//nolint:cyclop
-func (p *Parser) parseIntOrFloatOrDateTime(b []byte) (reference, []byte, error) {
- switch b[0] {
- case 'i':
- if !scanFollowsInf(b) {
- return invalidReference, nil, NewParserError(atmost(b, 3), "expected 'inf'")
- }
-
- return p.builder.Push(Node{
- Kind: Float,
- Data: b[:3],
- Raw: p.Range(b[:3]),
- }), b[3:], nil
- case 'n':
- if !scanFollowsNan(b) {
- return invalidReference, nil, NewParserError(atmost(b, 3), "expected 'nan'")
- }
-
- return p.builder.Push(Node{
- Kind: Float,
- Data: b[:3],
- Raw: p.Range(b[:3]),
- }), b[3:], nil
- case '+', '-':
- return p.scanIntOrFloat(b)
- }
-
- if len(b) < 3 {
- return p.scanIntOrFloat(b)
+// parseMultilineBasicString parses a multi-line basic string, starting at the
+// opening triple quote.
+func (p *Parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, error) {
+ i := 3
+ // trim the newline right after the opening delimiter
+ if i < len(b) && b[i] == '\n' {
+ i++
+ } else if i+1 < len(b) && b[i] == '\r' && b[i+1] == '\n' {
+ i += 2
}
+ contentStart := i
- s := 5
- if len(b) < s {
- s = len(b)
+ // First pass without allocating, until an escape sequence is found.
+ for i < len(b) {
+ c := b[i]
+ switch {
+ case c == '"':
+ j := i
+ for j < len(b) && b[j] == '"' {
+ j++
+ }
+ n := j - i
+ if n >= 3 {
+ if n > 5 {
+ return nil, nil, nil, NewParserError(b[i:j], "too many quotes at the end of a multiline basic string")
+ }
+ contentEnd := i + n - 3
+ return b[:j], b[contentStart:contentEnd], b[j:], nil
+ }
+ i = j
+ case c == '\\':
+ return p.parseMultilineBasicStringEscaped(b, contentStart, i)
+ case c >= 0x20 && c < 0x7f:
+ i++
+ case c == '\t' || c == '\n':
+ i++
+ case c == '\r':
+ if i+1 < len(b) && b[i+1] == '\n' {
+ i += 2
+ continue
+ }
+ return nil, nil, nil, NewParserError(b[i:i+1], "carriage returns must be followed by a newline character")
+ case c < 0x80:
+ return nil, nil, nil, NewParserError(b[i:i+1], "multiline basic strings cannot have control characters")
+ default:
+ var ok bool
+ i, ok = scanUtf8Run(b, i)
+ if !ok {
+ return nil, nil, nil, NewParserError(b[i:i+1], "invalid UTF-8 character in multiline basic string")
+ }
+ }
}
+ return nil, nil, nil, NewParserError(b[len(b):], `multiline basic string not terminated by """`)
+}
- for idx, c := range b[:s] {
- if isDigit(c) {
+// findMultilineBasicStringEnd returns the index of the first quote of the
+// run of quotes closing a multi-line basic string, or -1 if the string is
+// not terminated. It does not validate the content: it only skips over
+// escape sequences so that escaped quotes do not terminate the string.
+func findMultilineBasicStringEnd(b []byte, i int) int {
+ for {
+ j := bytes.IndexAny(b[i:], "\"\\")
+ if j < 0 {
+ return -1
+ }
+ i += j
+ if b[i] == '\\' {
+ i += 2
+ if i > len(b) {
+ return -1
+ }
continue
}
-
- if idx == 2 && c == ':' || (idx == 4 && c == '-') {
- return p.scanDateTime(b)
+ j = i
+ for j < len(b) && b[j] == '"' {
+ j++
}
-
- break
+ if j-i >= 3 {
+ return i
+ }
+ i = j
}
-
- return p.scanIntOrFloat(b)
}
-func (p *Parser) scanDateTime(b []byte) (reference, []byte, error) {
- // scans for contiguous characters in [0-9T:Z.+-], and up to one space if
- // followed by a digit.
- hasDate := false
- hasTime := false
- hasTz := false
- seenSpace := false
+// parseMultilineBasicStringEscaped continues parsing a multi-line basic
+// string that contains escape sequences. i is the index of the first
+// backslash; content starts at contentStart.
+func (p *Parser) parseMultilineBasicStringEscaped(b []byte, contentStart, i int) ([]byte, []byte, []byte, error) {
+ // Escape sequences only ever shrink, so the content length before
+ // unescaping is enough to never reallocate. The closing run of quotes
+ // can lend up to two quotes to the content.
+ bufCap := len(b) - contentStart
+ if end := findMultilineBasicStringEnd(b, i); end >= 0 {
+ bufCap = end + 2 - contentStart
+ }
+ buf := make([]byte, i-contentStart, bufCap)
+ copy(buf, b[contentStart:i])
- i := 0
-byteLoop:
- for ; i < len(b); i++ {
+ for i < len(b) {
c := b[i]
-
switch {
- case isDigit(c):
- case c == '-':
- hasDate = true
- const minOffsetOfTz = 8
- if i >= minOffsetOfTz {
- hasTz = true
+ case c == '"':
+ j := i
+ for j < len(b) && b[j] == '"' {
+ j++
}
- case c == 'T' || c == 't' || c == ':' || c == '.':
- hasTime = true
- case c == '+' || c == '-' || c == 'Z' || c == 'z':
- hasTz = true
- case c == ' ':
- if !seenSpace && i+1 < len(b) && isDigit(b[i+1]) {
- i += 2
- // Avoid reaching past the end of the document in case the time
- // is malformed. See TestIssue585.
- if i >= len(b) {
- i--
+ n := j - i
+ if n >= 3 {
+ if n > 5 {
+ return nil, nil, nil, NewParserError(b[i:j], "too many quotes at the end of a multiline basic string")
}
- seenSpace = true
- hasTime = true
- } else {
- break byteLoop
+ buf = append(buf, b[i:i+n-3]...)
+ return b[:j], buf, b[j:], nil
+ }
+ buf = append(buf, b[i:j]...)
+ i = j
+ case c == '\\':
+ i++
+ if i >= len(b) {
+ return nil, nil, nil, NewParserError(b[i-1:], `need a character after \`)
}
+ // Escaped newline: backslash, optional whitespace, newline,
+ // then all following whitespace and newlines are trimmed.
+ if b[i] == ' ' || b[i] == '\t' || b[i] == '\n' || b[i] == '\r' {
+ j := i
+ for j < len(b) && (b[j] == ' ' || b[j] == '\t') {
+ j++
+ }
+ if j < len(b) && b[j] == '\r' {
+ j++
+ }
+ if j >= len(b) || b[j] != '\n' {
+ return nil, nil, nil, NewParserError(b[i-1:i+1], "invalid escape character %#U", b[i])
+ }
+ j++
+ for j < len(b) && (b[j] == ' ' || b[j] == '\t' || b[j] == '\n' || b[j] == '\r') {
+ // note: a lone \r not followed by \n will be caught on
+ // the next iteration of the outer loop.
+ if b[j] == '\r' {
+ if j+1 >= len(b) || b[j+1] != '\n' {
+ break
+ }
+ j++
+ }
+ j++
+ }
+ i = j
+ continue
+ }
+ var err error
+ buf, i, err = unescape(buf, b, i)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ case c >= 0x20 && c < 0x7f:
+ buf = append(buf, c)
+ i++
+ case c == '\t' || c == '\n':
+ buf = append(buf, c)
+ i++
+ case c == '\r':
+ if i+1 < len(b) && b[i+1] == '\n' {
+ buf = append(buf, '\r', '\n')
+ i += 2
+ continue
+ }
+ return nil, nil, nil, NewParserError(b[i:i+1], "carriage returns must be followed by a newline character")
+ case c < 0x80:
+ return nil, nil, nil, NewParserError(b[i:i+1], "multiline basic strings cannot have control characters")
default:
- break byteLoop
- }
- }
-
- var kind Kind
-
- if hasTime {
- if hasDate {
- if hasTz {
- kind = DateTime
- } else {
- kind = LocalDateTime
+ j, ok := scanUtf8Run(b, i)
+ if !ok {
+ return nil, nil, nil, NewParserError(b[i:i+1], "invalid UTF-8 character in multiline basic string")
}
- } else {
- kind = LocalTime
+ buf = append(buf, b[i:j]...)
+ i = j
}
- } else {
- kind = LocalDate
}
-
- return p.builder.Push(Node{
- Kind: kind,
- Data: b[:i],
- }), b[i:], nil
+ return nil, nil, nil, NewParserError(b[len(b):], `multiline basic string not terminated by """`)
}
-//nolint:funlen,gocognit,cyclop
-func (p *Parser) scanIntOrFloat(b []byte) (reference, []byte, error) {
- i := 0
-
- if len(b) > 2 && b[0] == '0' && b[1] != '.' && b[1] != 'e' && b[1] != 'E' {
- var isValidRune validRuneFn
-
- switch b[1] {
- case 'x':
- isValidRune = isValidHexRune
- case 'o':
- isValidRune = isValidOctalRune
- case 'b':
- isValidRune = isValidBinaryRune
- default:
- i++
- }
-
- if isValidRune != nil {
+// scanUtf8Run consumes a run of valid non-ASCII UTF-8 runes starting at
+// b[i]. It returns the index of the first byte after the run, and whether
+// the run was entirely valid. Processing whole runs amortizes the cost of
+// the call compared to validating rune by rune.
+func scanUtf8Run(b []byte, i int) (int, bool) {
+ for i < len(b) {
+ c := b[i]
+ switch {
+ case c < 0x80:
+ return i, true
+ case c < 0xC2:
+ return i, false
+ case c < 0xE0:
+ if i+1 >= len(b) || b[i+1]&0xC0 != 0x80 {
+ return i, false
+ }
i += 2
- for ; i < len(b); i++ {
- if !isValidRune(b[i]) {
- break
+ case c < 0xF0:
+ if i+2 >= len(b) || b[i+2]&0xC0 != 0x80 {
+ return i, false
+ }
+ b1 := b[i+1]
+ switch c {
+ case 0xE0:
+ if b1 < 0xA0 || b1 > 0xBF {
+ return i, false
+ }
+ case 0xED:
+ // exclude surrogates
+ if b1 < 0x80 || b1 > 0x9F {
+ return i, false
+ }
+ default:
+ if b1&0xC0 != 0x80 {
+ return i, false
}
}
- }
-
- return p.builder.Push(Node{
- Kind: Integer,
- Data: b[:i],
- Raw: p.Range(b[:i]),
- }), b[i:], nil
- }
-
- isFloat := false
-
- for ; i < len(b); i++ {
- c := b[i]
-
- if c >= '0' && c <= '9' || c == '+' || c == '-' || c == '_' {
- continue
- }
-
- if c == '.' || c == 'e' || c == 'E' {
- isFloat = true
-
- continue
- }
-
- if c == 'i' {
- if scanFollowsInf(b[i:]) {
- return p.builder.Push(Node{
- Kind: Float,
- Data: b[:i+3],
- Raw: p.Range(b[:i+3]),
- }), b[i+3:], nil
+ i += 3
+ case c < 0xF5:
+ if i+3 >= len(b) || b[i+2]&0xC0 != 0x80 || b[i+3]&0xC0 != 0x80 {
+ return i, false
}
-
- return invalidReference, nil, NewParserError(b[i:i+1], "unexpected character 'i' while scanning for a number")
- }
-
- if c == 'n' {
- if scanFollowsNan(b[i:]) {
- return p.builder.Push(Node{
- Kind: Float,
- Data: b[:i+3],
- Raw: p.Range(b[:i+3]),
- }), b[i+3:], nil
+ b1 := b[i+1]
+ switch c {
+ case 0xF0:
+ if b1 < 0x90 || b1 > 0xBF {
+ return i, false
+ }
+ case 0xF4:
+ if b1 < 0x80 || b1 > 0x8F {
+ return i, false
+ }
+ default:
+ if b1&0xC0 != 0x80 {
+ return i, false
+ }
}
-
- return invalidReference, nil, NewParserError(b[i:i+1], "unexpected character 'n' while scanning for a number")
+ i += 4
+ default:
+ return i, false
}
-
- break
- }
-
- if i == 0 {
- return invalidReference, b, NewParserError(b, "incomplete number")
- }
-
- kind := Integer
-
- if isFloat {
- kind = Float
}
-
- return p.builder.Push(Node{
- Kind: kind,
- Data: b[:i],
- Raw: p.Range(b[:i]),
- }), b[i:], nil
-}
-
-func isDigit(r byte) bool {
- return r >= '0' && r <= '9'
-}
-
-type validRuneFn func(r byte) bool
-
-func isValidHexRune(r byte) bool {
- return r >= 'a' && r <= 'f' ||
- r >= 'A' && r <= 'F' ||
- r >= '0' && r <= '9' ||
- r == '_'
-}
-
-func isValidOctalRune(r byte) bool {
- return r >= '0' && r <= '7' || r == '_'
-}
-
-func isValidBinaryRune(r byte) bool {
- return r == '0' || r == '1' || r == '_'
-}
-
-func expect(x byte, b []byte) ([]byte, error) {
- if len(b) == 0 {
- return nil, NewParserError(b, "expected character %c but the document ended here", x)
- }
-
- if b[0] != x {
- return nil, NewParserError(b[0:1], "expected character %c", x)
- }
-
- return b[1:], nil
+ return i, true
}
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go b/vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go
deleted file mode 100644
index 0512181d..00000000
--- a/vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go
+++ /dev/null
@@ -1,270 +0,0 @@
-package unstable
-
-import "github.com/pelletier/go-toml/v2/internal/characters"
-
-func scanFollows(b []byte, pattern string) bool {
- n := len(pattern)
-
- return len(b) >= n && string(b[:n]) == pattern
-}
-
-func scanFollowsMultilineBasicStringDelimiter(b []byte) bool {
- return scanFollows(b, `"""`)
-}
-
-func scanFollowsMultilineLiteralStringDelimiter(b []byte) bool {
- return scanFollows(b, `'''`)
-}
-
-func scanFollowsTrue(b []byte) bool {
- return scanFollows(b, `true`)
-}
-
-func scanFollowsFalse(b []byte) bool {
- return scanFollows(b, `false`)
-}
-
-func scanFollowsInf(b []byte) bool {
- return scanFollows(b, `inf`)
-}
-
-func scanFollowsNan(b []byte) bool {
- return scanFollows(b, `nan`)
-}
-
-func scanUnquotedKey(b []byte) ([]byte, []byte) {
- // unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _
- for i := 0; i < len(b); i++ {
- if !isUnquotedKeyChar(b[i]) {
- return b[:i], b[i:]
- }
- }
-
- return b, b[len(b):]
-}
-
-func isUnquotedKeyChar(r byte) bool {
- return (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' || r == '_'
-}
-
-func scanLiteralString(b []byte) ([]byte, []byte, error) {
- // literal-string = apostrophe *literal-char apostrophe
- // apostrophe = %x27 ; ' apostrophe
- // literal-char = %x09 / %x20-26 / %x28-7E / non-ascii
- for i := 1; i < len(b); {
- switch b[i] {
- case '\'':
- return b[:i+1], b[i+1:], nil
- case '\n', '\r':
- return nil, nil, NewParserError(b[i:i+1], "literal strings cannot have new lines")
- }
- size := characters.Utf8ValidNext(b[i:])
- if size == 0 {
- return nil, nil, NewParserError(b[i:i+1], "invalid character")
- }
- i += size
- }
-
- return nil, nil, NewParserError(b[len(b):], "unterminated literal string")
-}
-
-func scanMultilineLiteralString(b []byte) ([]byte, []byte, error) {
- // ml-literal-string = ml-literal-string-delim [ newline ] ml-literal-body
- // ml-literal-string-delim
- // ml-literal-string-delim = 3apostrophe
- // ml-literal-body = *mll-content *( mll-quotes 1*mll-content ) [ mll-quotes ]
- //
- // mll-content = mll-char / newline
- // mll-char = %x09 / %x20-26 / %x28-7E / non-ascii
- // mll-quotes = 1*2apostrophe
- for i := 3; i < len(b); {
- switch b[i] {
- case '\'':
- if scanFollowsMultilineLiteralStringDelimiter(b[i:]) {
- i += 3
-
- // At that point we found 3 apostrophe, and i is the
- // index of the byte after the third one. The scanner
- // needs to be eager, because there can be an extra 2
- // apostrophe that can be accepted at the end of the
- // string.
-
- if i >= len(b) || b[i] != '\'' {
- return b[:i], b[i:], nil
- }
- i++
-
- if i >= len(b) || b[i] != '\'' {
- return b[:i], b[i:], nil
- }
- i++
-
- if i < len(b) && b[i] == '\'' {
- return nil, nil, NewParserError(b[i-3:i+1], "''' not allowed in multiline literal string")
- }
-
- return b[:i], b[i:], nil
- }
- case '\r':
- if len(b) < i+2 {
- return nil, nil, NewParserError(b[len(b):], `need a \n after \r`)
- }
- if b[i+1] != '\n' {
- return nil, nil, NewParserError(b[i:i+2], `need a \n after \r`)
- }
- i += 2 // skip the \n
- continue
- }
- size := characters.Utf8ValidNext(b[i:])
- if size == 0 {
- return nil, nil, NewParserError(b[i:i+1], "invalid character")
- }
- i += size
- }
-
- return nil, nil, NewParserError(b[len(b):], `multiline literal string not terminated by '''`)
-}
-
-func scanWindowsNewline(b []byte) ([]byte, []byte, error) {
- const lenCRLF = 2
- if len(b) < lenCRLF {
- return nil, nil, NewParserError(b, "windows new line expected")
- }
-
- if b[1] != '\n' {
- return nil, nil, NewParserError(b, `windows new line should be \r\n`)
- }
-
- return b[:lenCRLF], b[lenCRLF:], nil
-}
-
-func scanWhitespace(b []byte) ([]byte, []byte) {
- for i := 0; i < len(b); i++ {
- switch b[i] {
- case ' ', '\t':
- continue
- default:
- return b[:i], b[i:]
- }
- }
-
- return b, b[len(b):]
-}
-
-func scanComment(b []byte) ([]byte, []byte, error) {
- // comment-start-symbol = %x23 ; #
- // non-ascii = %x80-D7FF / %xE000-10FFFF
- // non-eol = %x09 / %x20-7F / non-ascii
- //
- // comment = comment-start-symbol *non-eol
-
- for i := 1; i < len(b); {
- if b[i] == '\n' {
- return b[:i], b[i:], nil
- }
- if b[i] == '\r' {
- if i+1 < len(b) && b[i+1] == '\n' {
- return b[:i+1], b[i+1:], nil
- }
- return nil, nil, NewParserError(b[i:i+1], "invalid character in comment")
- }
- size := characters.Utf8ValidNext(b[i:])
- if size == 0 {
- return nil, nil, NewParserError(b[i:i+1], "invalid character in comment")
- }
-
- i += size
- }
-
- return b, b[len(b):], nil
-}
-
-func scanBasicString(b []byte) ([]byte, bool, []byte, error) {
- // basic-string = quotation-mark *basic-char quotation-mark
- // quotation-mark = %x22 ; "
- // basic-char = basic-unescaped / escaped
- // basic-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
- // escaped = escape escape-seq-char
- escaped := false
- i := 1
-
- for ; i < len(b); i++ {
- switch b[i] {
- case '"':
- return b[:i+1], escaped, b[i+1:], nil
- case '\n', '\r':
- return nil, escaped, nil, NewParserError(b[i:i+1], "basic strings cannot have new lines")
- case '\\':
- if len(b) < i+2 {
- return nil, escaped, nil, NewParserError(b[i:i+1], "need a character after \\")
- }
- escaped = true
- i++ // skip the next character
- }
- }
-
- return nil, escaped, nil, NewParserError(b[len(b):], `basic string not terminated by "`)
-}
-
-func scanMultilineBasicString(b []byte) ([]byte, bool, []byte, error) {
- // ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
- // ml-basic-string-delim
- // ml-basic-string-delim = 3quotation-mark
- // ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ]
- //
- // mlb-content = mlb-char / newline / mlb-escaped-nl
- // mlb-char = mlb-unescaped / escaped
- // mlb-quotes = 1*2quotation-mark
- // mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
- // mlb-escaped-nl = escape ws newline *( wschar / newline )
-
- escaped := false
- i := 3
-
- for ; i < len(b); i++ {
- switch b[i] {
- case '"':
- if scanFollowsMultilineBasicStringDelimiter(b[i:]) {
- i += 3
-
- // At that point we found 3 apostrophe, and i is the
- // index of the byte after the third one. The scanner
- // needs to be eager, because there can be an extra 2
- // apostrophe that can be accepted at the end of the
- // string.
-
- if i >= len(b) || b[i] != '"' {
- return b[:i], escaped, b[i:], nil
- }
- i++
-
- if i >= len(b) || b[i] != '"' {
- return b[:i], escaped, b[i:], nil
- }
- i++
-
- if i < len(b) && b[i] == '"' {
- return nil, escaped, nil, NewParserError(b[i-3:i+1], `""" not allowed in multiline basic string`)
- }
-
- return b[:i], escaped, b[i:], nil
- }
- case '\\':
- if len(b) < i+2 {
- return nil, escaped, nil, NewParserError(b[len(b):], "need a character after \\")
- }
- escaped = true
- i++ // skip the next character
- case '\r':
- if len(b) < i+2 {
- return nil, escaped, nil, NewParserError(b[len(b):], `need a \n after \r`)
- }
- if b[i+1] != '\n' {
- return nil, escaped, nil, NewParserError(b[i:i+2], `need a \n after \r`)
- }
- i++ // skip the \n
- }
- }
-
- return nil, escaped, nil, NewParserError(b[len(b):], `multiline basic string not terminated by """`)
-}
diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go b/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go
index 00cfd6de..c84c90cc 100644
--- a/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go
@@ -1,7 +1,43 @@
package unstable
-// The Unmarshaler interface may be implemented by types to customize their
-// behavior when being unmarshaled from a TOML document.
+// Unmarshaler is implemented by types that can unmarshal a TOML description
+// of themselves. The input is a valid TOML document containing the relevant
+// portion of the parsed document.
+//
+// For tables (including split tables defined in multiple places), the data
+// contains the raw key-value bytes from the original document with adjusted
+// table headers to be relative to the unmarshaling target.
+//
+// When the decoding target itself implements this interface, it receives the
+// whole document — every top-level key-value as well as every table and array
+// table — assembled into a single valid TOML document and delivered once.
type Unmarshaler interface {
- UnmarshalTOML(value *Node) error
+ UnmarshalTOML(data []byte) error
+}
+
+// RawMessage is a raw encoded TOML value. It implements both Unmarshaler and
+// Marshaler and can be used to delay TOML decoding or capture raw content,
+// similar to json.RawMessage.
+//
+// Decoding (requires Decoder.EnableUnmarshalerInterface) captures the raw TOML
+// bytes for the target without decoding them:
+//
+// type Config struct {
+// Plugin RawMessage `toml:"plugin"`
+// }
+//
+// var cfg Config
+// toml.NewDecoder(r).EnableUnmarshalerInterface().Decode(&cfg)
+// // cfg.Plugin now contains the raw TOML bytes for [plugin]
+//
+// Encoding (requires Encoder.EnableMarshalerInterface) splices the stored bytes
+// back into the document verbatim:
+//
+// toml.NewEncoder(w).EnableMarshalerInterface().Encode(cfg)
+type RawMessage []byte
+
+// UnmarshalTOML implements Unmarshaler.
+func (m *RawMessage) UnmarshalTOML(data []byte) error {
+ *m = append((*m)[:0], data...)
+ return nil
}
diff --git a/vendor/github.com/raeperd/recvcheck/.golangci.yml b/vendor/github.com/raeperd/recvcheck/.golangci.yml
index 18692d50..3ef4d52f 100644
--- a/vendor/github.com/raeperd/recvcheck/.golangci.yml
+++ b/vendor/github.com/raeperd/recvcheck/.golangci.yml
@@ -1,10 +1,14 @@
+version: "2"
+
+formatters:
+ enable:
+ - gofumpt
+ - gci
+
linters:
enable:
- recvcheck
-
-output:
- show-stats: true
- sort-results: true
- sort-order:
- - linter
- - file
+ exclusions:
+ presets:
+ - common-false-positives
+ - std-error-handling
diff --git a/vendor/github.com/raeperd/recvcheck/README.md b/vendor/github.com/raeperd/recvcheck/README.md
index 067aa3c5..e51acda8 100644
--- a/vendor/github.com/raeperd/recvcheck/README.md
+++ b/vendor/github.com/raeperd/recvcheck/README.md
@@ -1,52 +1,136 @@
# recvcheck
-[](https://github.com/raeperd/recvcheck/actions/workflows/build.yaml) [](https://goreportcard.com/report/github.com/raeperd/recvcheck)
-Golang linter for check receiver type in method
-## Motivation
-From [Go Wiki: Go Code Review Comments - The Go Programming Language](https://go.dev/wiki/CodeReviewComments#receiver-type)
-> Don’t mix receiver types. Choose either pointers or struct types for all available method
+[](https://github.com/raeperd/recvcheck/actions/workflows/build.yaml)
+[](https://goreportcard.com/report/github.com/raeperd/recvcheck)
+[](https://coveralls.io/github/raeperd/recvcheck?branch=main)
+[](https://pkg.go.dev/github.com/raeperd/recvcheck)
-Following code from [Dave Cheney](https://dave.cheney.net/2015/11/18/wednesday-pop-quiz-spot-the-race) causes data race. Could you find it?
-This linter does it for you.
+Go linter that detects mixing pointer and value method receivers.
-```go
-package main
+## Why
+
+Mixing pointer and value receivers on the same type creates **subtle, hard-to-detect bugs** that can cause:
-import (
- "fmt"
- "time"
-)
+### 🐛 Data Races
+When you copy a struct with a mutex, you copy the mutex state, leading to race conditions:
+```go
type RPC struct {
- result int
- done chan struct{}
+ mu sync.Mutex // This is the problem!
+ result int
+ done chan struct{}
}
func (rpc *RPC) compute() {
- time.Sleep(time.Second) // strenuous computation intensifies
- rpc.result = 42
- close(rpc.done)
+ rpc.mu.Lock()
+ defer rpc.mu.Unlock()
+ rpc.result = 42
}
-func (RPC) version() int {
- return 1 // never going to need to change this
+func (RPC) version() int { // Value receiver copies the mutex!
+ return 1
}
func main() {
- rpc := &RPC{done: make(chan struct{})}
+ rpc := &RPC{done: make(chan struct{})}
+ go rpc.compute() // Locks original mutex
+ version := rpc.version() // Uses copied mutex - RACE!
+ // ...
+}
+```
- go rpc.compute() // kick off computation in the background
- version := rpc.version() // grab some other information while we're waiting
- <-rpc.done // wait for computation to finish
- result := rpc.result
+### 🚨 Silent Bugs
- fmt.Printf("RPC computation complete, result: %d, version: %d\n", result, version)
+Value receivers create copies, so modifications are lost:
+
+```go
+type Counter struct {
+ value int
}
+
+func (c *Counter) Increment() { c.value++ } // pointer receiver
+func (c Counter) Reset() { c.value = 0 } // value receiver - NO EFFECT!
+```
+
+### 🤔 Developer Confusion
+
+Mixed receivers make code behavior unpredictable and harder to reason about.
+
+### ✅ The Solution
+
+**Consistency is key**: Go's official guidance says [Don't mix receiver types](https://go.dev/wiki/CodeReviewComments#receiver-type). Choose either pointers or values for **all** methods on a type.
+
+`recvcheck` automatically detects these issues before they reach production.
+
+## Installation
+
+```bash
+# Standalone
+go install github.com/raeperd/recvcheck/cmd/recvcheck@latest
+
+# With golangci-lint (recommended)
+# Add to .golangci.yml:
+linters:
+ enable:
+ - recvcheck
+```
+
+## Usage
+
+```bash
+recvcheck ./...
+# or
+golangci-lint run
+```
+
+Output:
+```
+main.go:8:1: the methods of "RPC" use pointer receiver and non-pointer receiver
+```
+
+## Configuration
+
+```yaml
+# .golangci.yml
+linters-settings:
+ recvcheck:
+ # Disable default exclusions (MarshalJSON, etc.)
+ disable-builtin: false
+
+ # Custom exclusions
+ exclusions:
+ - "Server.Shutdown" # Specific method
+ - "*.String" # All String methods
+```
+
+### Default Exclusions
+
+Unmarshal methods are excluded by default as they must use pointer receivers:
+- `*.UnmarshalText`, `*.UnmarshalJSON`, `*.UnmarshalYAML`
+- `*.UnmarshalXML`, `*.UnmarshalBinary`, `*.GobDecode`
+
+## Examples
+
+❌ **Bad** - Mixed receivers:
+```go
+func (u *User) SetName(name string) { } // pointer
+func (u User) GetName() string { } // value - inconsistent!
```
-## References
-- [Is there a way to detect following data race code using golangci-lint or other linter?? · golangci/golangci-lint · Discussion #5006](https://github.com/golangci/golangci-lint/discussions/5006)
- - [Wednesday pop quiz: spot the race | Dave Cheney](https://dave.cheney.net/2015/11/18/wednesday-pop-quiz-spot-the-race)
+✅ **Good** - Consistent receivers:
+```go
+func (u *User) SetName(name string) { } // pointer
+func (u *User) GetName() string { } // pointer - consistent!
+```
+## Contributing
+
+```bash
+make test # Run tests
+make lint # Run linter
+make build # Build binary
+```
+## License
+MIT
\ No newline at end of file
diff --git a/vendor/github.com/raeperd/recvcheck/analyzer.go b/vendor/github.com/raeperd/recvcheck/analyzer.go
index 11fb38e7..a67d72e8 100644
--- a/vendor/github.com/raeperd/recvcheck/analyzer.go
+++ b/vendor/github.com/raeperd/recvcheck/analyzer.go
@@ -15,14 +15,14 @@ func NewAnalyzer(s Settings) *analysis.Analyzer {
}
if !s.DisableBuiltin {
- // Default excludes for Marshal/Encode methods https://github.com/raeperd/recvcheck/issues/7
+ // Default excludes for Unmarshal/Decode methods https://github.com/raeperd/recvcheck/issues/17
a.excluded = map[string]struct{}{
- "*.MarshalText": {},
- "*.MarshalJSON": {},
- "*.MarshalYAML": {},
- "*.MarshalXML": {},
- "*.MarshalBinary": {},
- "*.GobEncode": {},
+ "*.UnmarshalText": {},
+ "*.UnmarshalJSON": {},
+ "*.UnmarshalYAML": {},
+ "*.UnmarshalXML": {},
+ "*.UnmarshalBinary": {},
+ "*.GobDecode": {},
}
}
@@ -42,12 +42,12 @@ func NewAnalyzer(s Settings) *analysis.Analyzer {
type Settings struct {
// DisableBuiltin if true, disables the built-in method excludes.
// Built-in excluded methods:
- // - "MarshalText"
- // - "MarshalJSON"
- // - "MarshalYAML"
- // - "MarshalXML"
- // - "MarshalBinary"
- // - "GobEncode"
+ // - "UnmarshalText"
+ // - "UnmarshalJSON"
+ // - "UnmarshalYAML"
+ // - "UnmarshalXML"
+ // - "UnmarshalBinary"
+ // - "GobDecode"
DisableBuiltin bool
// Exclusions format is `struct_name.method_name` (ex: `Foo.MethodName`).
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/.dockerignore b/vendor/github.com/ryancurrah/gomodguard/v2/.dockerignore
new file mode 100644
index 00000000..77738287
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/.dockerignore
@@ -0,0 +1 @@
+dist/
\ No newline at end of file
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/.gitignore b/vendor/github.com/ryancurrah/gomodguard/v2/.gitignore
new file mode 100644
index 00000000..4ebc79c5
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/.gitignore
@@ -0,0 +1,25 @@
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
+
+/gomodguard
+
+*.xml
+
+dist/
+
+coverage.*
+
+.idea/
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/.golangci.yml b/vendor/github.com/ryancurrah/gomodguard/v2/.golangci.yml
new file mode 100644
index 00000000..2e3266ad
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/.golangci.yml
@@ -0,0 +1,35 @@
+version: "2"
+
+linters:
+ default: all
+ disable:
+ - lll
+ - gomodguard
+ - gomoddirectives
+ - gochecknoglobals
+ - paralleltest
+ - varnamelen
+ - exhaustruct
+ - depguard
+ - forbidigo
+ - funlen
+ - nlreturn
+ - nonamedreturns
+ - cyclop
+ - err113
+ - perfsprint
+ - tagliatelle
+ - wrapcheck
+ - mnd
+ - wsl
+ - noinlineerr
+ settings:
+ revive:
+ rules:
+ - name: package-comments
+ disabled: true
+ exclusions:
+ rules:
+ - path: _test\.go$
+ linters:
+ - goconst
diff --git a/vendor/github.com/aymanbagabas/go-osc52/v2/LICENSE b/vendor/github.com/ryancurrah/gomodguard/v2/LICENSE
similarity index 96%
rename from vendor/github.com/aymanbagabas/go-osc52/v2/LICENSE
rename to vendor/github.com/ryancurrah/gomodguard/v2/LICENSE
index 25cec1ed..acd8a81e 100644
--- a/vendor/github.com/aymanbagabas/go-osc52/v2/LICENSE
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2022 Ayman Bagabas
+Copyright (c) 2020 Ryan Currah
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/Makefile b/vendor/github.com/ryancurrah/gomodguard/v2/Makefile
new file mode 100644
index 00000000..d30a2255
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/Makefile
@@ -0,0 +1,87 @@
+current_dir = $(shell pwd)
+
+.PHONY: goimports
+goimports:
+ find . -name '*.go' -exec goimports -w -local github.com/ryancurrah/gomodguard {} +
+
+.PHONY: lint
+lint:
+ golangci-lint run ./...
+ cd cmd/gomodguard && golangci-lint run ./...
+
+.PHONY: tidy
+tidy:
+ go mod tidy
+ cd cmd/gomodguard && go mod tidy
+
+.PHONY: build
+build:
+ cd cmd/gomodguard && go build -o "$$(go env GOPATH)/bin/gomodguard" main.go
+
+.PHONY: run
+run: build
+ ./gomodguard
+
+.PHONY: test
+test:
+ go test -v -coverprofile coverage.out
+ cd cmd/gomodguard && go test -v -coverprofile coverage.out ./...
+ cat cmd/gomodguard/coverage.out | tail -n +2 >> coverage.out
+
+.PHONY: cover
+cover:
+ gocover-cobertura < coverage.out > coverage.xml
+
+.PHONY: dockerrun
+dockerrun: dockerbuild
+ docker run -v "${current_dir}/.gomodguard.yaml:/.gomodguard.yaml" ryancurrah/gomodguard:latest
+
+.PHONY: snapshot
+snapshot:
+ cd cmd/gomodguard && goreleaser --clean --snapshot
+
+.PHONY: release
+release:
+ cd cmd/gomodguard && goreleaser --clean
+
+.PHONY: clean
+clean:
+ rm -rf dist/
+ rm -f gomodguard coverage.xml coverage.out
+ rm -f cmd/gomodguard/coverage.out
+
+.PHONY: tag
+tag:
+ @if [ -n "$$(git status --porcelain)" ]; then \
+ echo "error: working tree not clean"; exit 1; \
+ fi; \
+ current=$$(git tag --sort=-v:refname --list 'v*' | head -n1 || echo "none"); \
+ read -p "Current version: $$current. Enter new version: " version; \
+ if [ -z "$$version" ]; then echo "error: version required"; exit 1; fi; \
+ bump_branch="bump-library-to-$$version"; \
+ git tag "$$version" && \
+ git push origin "$$version" && \
+ git checkout -b "$$bump_branch" && \
+ (cd cmd/gomodguard && GOWORK=off go get "github.com/ryancurrah/gomodguard/v2@$$version" && GOWORK=off go mod tidy) && \
+ git add cmd/gomodguard/go.mod cmd/gomodguard/go.sum && \
+ git commit -m "chore: bump library to $$version" && \
+ git tag "cmd/gomodguard/$$version" && \
+ git push -u origin "$$bump_branch" "cmd/gomodguard/$$version" && \
+ gh pr create --title "chore: bump library to $$version" --body "Required by cmd/gomodguard/$$version release." && \
+ echo "waiting for PR to merge..." && \
+ while :; do \
+ state=$$(gh pr view --json state -q .state); \
+ if [ "$$state" = "MERGED" ]; then break; fi; \
+ if [ "$$state" = "CLOSED" ]; then echo "error: PR closed without merge"; exit 1; fi; \
+ sleep 30; \
+ done && \
+ git checkout main && git pull --ff-only origin main && \
+ git branch -D "$$bump_branch"
+
+.PHONY: install-mac-tools
+install-tools-mac:
+ brew install goreleaser/tap/goreleaser
+
+.PHONY: install-go-tools
+install-go-tools:
+ go install -v github.com/t-yuki/gocover-cobertura@latest
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/README.md b/vendor/github.com/ryancurrah/gomodguard/v2/README.md
new file mode 100644
index 00000000..a0bea99f
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/README.md
@@ -0,0 +1,219 @@
+# gomodguard
+[](/LICENSE)
+[](https://codecov.io/gh/ryancurrah/gomodguard)
+[](https://github.com/ryancurrah/gomodguard/actions?query=workflow%3AGo)
+[](https://github.com/ryancurrah/gomodguard/releases/latest)
+[](https://hub.docker.com/r/ryancurrah/gomodguard)
+[](https://somsubhra.com/github-release-stats/?username=ryancurrah&repository=gomodguard)
+
+
+
+Allow and block list linter for direct Go module dependencies. This is useful for organizations where they want to standardize on the modules used and be able to recommend alternative modules.
+
+## Description
+
+Allowed and blocked modules are defined in a `./.gomodguard.yaml` or `~/.gomodguard.yaml` file.
+
+Modules can be allowed by module or prefix name. When allowed modules are specified any modules not in the allowed configuration are blocked.
+
+If no allowed modules or module prefixes are specified then all modules are allowed except for blocked ones.
+
+The linter looks for blocked modules in `go.mod` and searches for imported packages where the imported packages module is blocked. Indirect modules are not considered.
+
+Alternative modules can be optionally recommended in the blocked modules list.
+
+If the linted module imports a blocked module but the linted module is in the recommended modules list the blocked module is ignored. Usually, this means the linted module wraps that blocked module for use by other modules, therefore the import of the blocked module should not be blocked.
+
+Version constraints can be specified for modules as well which lets you block new or old versions of modules or specific versions.
+
+Results are printed to `stdout`.
+
+Logging statements are printed to `stderr`.
+
+Results can be exported to different report formats. Which can be imported into CI tools. See the help section for more information.
+
+# Configuration
+
+```yaml
+# allowed defines the modules that are permitted as direct dependencies.
+# When this section is non-empty, any module not matched by an entry is blocked.
+# When omitted entirely, all modules are allowed except those in the blocked list.
+allowed:
+ # Exact match (default when match-type is omitted).
+ - module: go.yaml.in/yaml/v4
+ - module: github.com/go-xmlfmt/xmlfmt
+
+ # version constrains which versions of the module are allowed.
+ # Uses semver constraint syntax (e.g. ">= 1.0.0", "~1.2", "== 2.5.0").
+ - module: github.com/confluentinc/confluent-kafka-go/v2
+ version: "== 2.5.0"
+
+ # match-type controls how the module is matched against module paths.
+ # Options: exact (default), prefix, regex
+ - module: github.com/kubernetes
+ match-type: prefix
+ - module: github.com/apache/arrow-go
+ match-type: prefix
+ - module: "github.com/somecompany/.*"
+ match-type: regex
+
+# blocked defines modules that are not permitted as direct dependencies.
+blocked:
+ - module: github.com/uudashr/go-module
+ # match-type controls how the module is matched against module paths.
+ # Options: exact (default), prefix, regex
+ match-type: exact
+
+ # recommendations lists alternative modules to suggest in the lint error.
+ recommendations:
+ - golang.org/x/mod
+
+ # reason is a human-readable explanation appended to the lint error.
+ reason: "`mod` is the official go.mod parser library."
+
+ - module: github.com/mitchellh/go-homedir
+ # version constrains which versions of the module are blocked.
+ # Uses semver constraint syntax. When omitted, all versions are blocked.
+ version: "<= 1.1.0"
+ reason: "old versions have a known bug."
+
+ - module: "github.com/badcompany/.*"
+ match-type: regex
+ reason: "No badcompany packages are permitted."
+
+# Blocks 'replace' directives using local filesystem paths to prevent
+# accidental commits of dev overrides. Sibling modules in multi-module
+# repos are automatically detected and permitted.
+local_replace_directives: true
+```
+
+### Field reference
+
+#### Top-level fields
+
+| Field | Type | Default | Description |
+|---|---|---|---|
+| `allowed` | list | *(none)* | Modules that are permitted. When non-empty, anything not matched is blocked. |
+| `blocked` | list | *(none)* | Modules that are explicitly blocked. |
+| `local_replace_directives` | bool | `false` | Block any module whose `replace` directive points to a local filesystem path. Multi-module repo aware: sibling modules whose replacement path contains a matching `go.mod` are not blocked. |
+
+#### `allowed` / `blocked` entry fields
+
+| Field | Type | Description |
+|---|---|---|
+| `module` | string | The module path to match against. |
+| `match-type` | `exact` \| `prefix` \| `regex` | How `module` is matched against dependency paths. Defaults to `exact`. |
+| `version` | semver constraint string | Restricts the rule to specific versions (e.g. `<= 1.2.0`, `>= 2.0.0`). When omitted, all versions match. |
+| `recommendations` | list of module paths | *(blocked only)* Alternative modules to suggest in the lint error. If the module being linted is itself in this list, the block is skipped. |
+| `reason` | string | *(blocked only)* Human-readable explanation appended to the lint error. |
+
+#### Match type precedence
+
+When multiple rules can match the same module the following precedence applies:
+
+1. **Exact match** — highest priority; wins over prefix and regex.
+2. **Prefix match** — next priority; longest matching prefix wins.
+3. **Regex match** — lowest priority; evaluated in alphabetical key order; first match wins.
+
+## Example .gomodguard.yaml Files
+
+The following example configuration files are available:
+
+- [examples/alloptions/.gomodguard.yaml](examples/alloptions/.gomodguard.yaml)
+- [examples/allowedversion/.gomodguard.yaml](examples/allowedversion/.gomodguard.yaml)
+- [examples/emptyallowlist/.gomodguard.yaml](examples/emptyallowlist/.gomodguard.yaml)
+- [examples/indirectdep/.gomodguard.yaml](examples/indirectdep/.gomodguard.yaml)
+- [examples/majorversion/.gomodguard.yaml](examples/majorversion/.gomodguard.yaml)
+- [examples/regexversion/.gomodguard.yaml](examples/regexversion/.gomodguard.yaml)
+- [examples/regextest/.gomodguard.yaml](examples/regextest/.gomodguard.yaml)
+
+### Migrating from v1
+
+If you have a v1 `.gomodguard.yaml` file, you can automatically migrate it to the new v2 schema by running:
+
+```
+gomodguard migrate > .gomodguard-v2.yaml
+mv .gomodguard-v2.yaml .gomodguard.yaml
+```
+
+## Usage
+
+```
+╰─ gomodguard -help
+Usage: gomodguard [files...]
+Also supports package syntax but will use it in relative path, i.e. ./pkg/...
+
+Commands:
+ (default) Lint Go module dependencies using the configuration file
+ migrate Convert a v1 .gomodguard.yaml config file to v2 format and print to stdout
+
+Flags:
+ -f string
+ Report results to the specified file. A report type must also be specified
+ -file string
+
+ -h Show this help text
+ -help
+
+ -i int
+ Exit code when issues were found (default 2)
+ -issues-exit-code int
+ (default 2)
+ -n Don't lint test files
+ -no-test
+
+ -r string
+ Report results to one of the following formats: checkstyle. A report file destination must also be specified
+ -report string
+
+ -version
+ Print the version
+```
+
+## Example
+
+```
+╰─ cd examples/alloptions
+╰─ gomodguard -r checkstyle -f gomodguard-checkstyle.xml ./...
+
+info: allowed modules, [github.com/Masterminds/semver/v3 github.com/go-xmlfmt/xmlfmt golang.org gopkg.in/yaml.v3]
+info: blocked modules, [github.com/gofrs/uuid github.com/mitchellh/go-homedir github.com/uudashr/go-module]
+blocked_example.go:6:1 import of package `github.com/gofrs/uuid` is blocked because the module is in the blocked modules list. `github.com/ryancurrah/gomodguard` is a recommended module. testing if module is not blocked when it is recommended.
+blocked_example.go:7:1 import of package `github.com/mitchellh/go-homedir` is blocked because the module is in the blocked modules list. version `v1.1.0` is blocked because it does not meet the version constraint `<=1.1.0`. testing if blocked version constraint works.
+blocked_example.go:8:1 import of package `github.com/uudashr/go-module` is blocked because the module is in the blocked modules list. `golang.org/x/mod` is a recommended module. `mod` is the official go.mod parser library.
+```
+
+Resulting checkstyle file
+
+```
+╰─ cat gomodguard-checkstyle.xml
+
+
+
+
+
+
+
+
+
+```
+
+## Install
+
+```
+go install github.com/ryancurrah/gomodguard/cmd/gomodguard/v2@latest
+```
+
+## Develop
+
+```
+git clone https://github.com/ryancurrah/gomodguard.git && cd gomodguard/cmd/gomodguard
+
+go build -o gomodguard main.go
+```
+
+The repository is a multi-module workspace: the library lives at the root and the CLI lives under `cmd/gomodguard`. A `go.work` file at the repo root wires them together so local CLI builds pick up local library changes without needing a `replace` directive in `cmd/gomodguard/go.mod`.
+
+## License
+
+**MIT**
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/allowed.go b/vendor/github.com/ryancurrah/gomodguard/v2/allowed.go
new file mode 100644
index 00000000..536a74cb
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/allowed.go
@@ -0,0 +1,42 @@
+package gomodguard
+
+import (
+ "fmt"
+
+ "github.com/Masterminds/semver/v3"
+)
+
+// Allowed is a list of modules that are allowed to be used.
+type Allowed []AllowedModule
+
+// AllowedModule is a single entry in the allowed list.
+type AllowedModule struct {
+ Module string `yaml:"module"`
+ MatchType MatchType `yaml:"match-type"`
+ Version *semver.Constraints `yaml:"version"`
+ Matcher Matcher `yaml:"-"`
+}
+
+// CheckVersion returns true if the module version matches the allowed constraint,
+// or if no version constraint is specified.
+func (r *AllowedModule) CheckVersion(moduleVersion string) (bool, error) {
+ if r.Version == nil {
+ return true, nil
+ }
+
+ version, err := semver.NewVersion(moduleVersion)
+ if err != nil {
+ return false, err
+ }
+
+ return r.Version.Check(version), nil
+}
+
+// NotAllowedReason returns the reason why the module version is not allowed.
+func (r *AllowedModule) NotAllowedReason(moduleVersion string) string {
+ if r == nil || r.Version == nil {
+ return "the module is not in the allowed modules list."
+ }
+
+ return fmt.Sprintf("version `%s` does not meet the allowed version constraint `%s`.", moduleVersion, r.Version)
+}
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/blocked.go b/vendor/github.com/ryancurrah/gomodguard/v2/blocked.go
new file mode 100644
index 00000000..5ba7ee1f
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/blocked.go
@@ -0,0 +1,99 @@
+package gomodguard
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/Masterminds/semver/v3"
+)
+
+// Blocked is a list of modules that are blocked and not to be used.
+type Blocked []BlockedModule
+
+// BlockedModule is a single entry in the blocked list.
+type BlockedModule struct {
+ Module string `yaml:"module"`
+ MatchType MatchType `yaml:"match-type"`
+ Recommendations []string `yaml:"recommendations"`
+ Reason string `yaml:"reason"`
+ Version *semver.Constraints `yaml:"version"`
+ Matcher Matcher `yaml:"-"`
+}
+
+// CheckVersion returns true if the module version matches the blocked constraint.
+// If no version constraint is specified, all versions are considered blocked.
+func (r *BlockedModule) CheckVersion(moduleVersion string) (bool, error) {
+ if r.Version == nil {
+ return true, nil
+ }
+
+ version, err := semver.NewVersion(moduleVersion)
+ if err != nil {
+ return true, err
+ }
+
+ return r.Version.Check(version), nil
+}
+
+// BlockReason returns the reason why the module or version is blocked.
+func (r *BlockedModule) BlockReason(currentModuleVersion string) string {
+ var sb strings.Builder
+
+ if r.Version != nil {
+ _, _ = fmt.Fprintf(&sb, "version `%s` is blocked because it does not meet the version constraint `%s`.",
+ currentModuleVersion, r.Version)
+ }
+
+ if len(r.Recommendations) > 0 {
+ if sb.Len() > 0 {
+ sb.WriteString(" ")
+ }
+
+ for i := range r.Recommendations {
+ switch {
+ case len(r.Recommendations) == 1:
+ _, _ = fmt.Fprintf(&sb, "`%s` is a recommended module.", r.Recommendations[i])
+ case (i+1) != len(r.Recommendations) && (i+1) == (len(r.Recommendations)-1):
+ _, _ = fmt.Fprintf(&sb, "`%s` ", r.Recommendations[i])
+ case (i + 1) != len(r.Recommendations):
+ _, _ = fmt.Fprintf(&sb, "`%s`, ", r.Recommendations[i])
+ default:
+ _, _ = fmt.Fprintf(&sb, "and `%s` are recommended modules.", r.Recommendations[i])
+ }
+ }
+ }
+
+ if r.Reason != "" {
+ if sb.Len() > 0 {
+ _, _ = fmt.Fprintf(&sb, " %s.", strings.TrimRight(r.Reason, "."))
+ } else {
+ _, _ = fmt.Fprintf(&sb, "%s.", strings.TrimRight(r.Reason, "."))
+ }
+ }
+
+ return sb.String()
+}
+
+// IsCurrentModuleARecommendation returns true if the current module is in the Recommendations list.
+func (r *BlockedModule) IsCurrentModuleARecommendation(currentModuleName string) bool {
+ if r == nil {
+ return false
+ }
+
+ for n := range r.Recommendations {
+ if strings.TrimSpace(currentModuleName) == strings.TrimSpace(r.Recommendations[n]) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// HasRecommendations returns true if the blocked package has recommended modules.
+func (r *BlockedModule) HasRecommendations() bool {
+ if r == nil {
+ return false
+ }
+
+ return len(r.Recommendations) > 0
+}
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/codecov.yml b/vendor/github.com/ryancurrah/gomodguard/v2/codecov.yml
new file mode 100644
index 00000000..4c475c7c
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/codecov.yml
@@ -0,0 +1,9 @@
+coverage:
+ status:
+ project:
+ default:
+ target: auto
+ threshold: 5%
+ patch:
+ default:
+ target: auto
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/filesearch.go b/vendor/github.com/ryancurrah/gomodguard/v2/filesearch.go
new file mode 100644
index 00000000..4c4769d7
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/filesearch.go
@@ -0,0 +1,66 @@
+package gomodguard
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// Find returns files based on search string arguments and filters.
+func Find(cwd string, skipTests bool, args []string) []string {
+ var (
+ foundFiles = []string{}
+ filteredFiles = []string{}
+ )
+
+ for _, f := range args {
+ if strings.HasSuffix(f, "/...") {
+ dir, _ := filepath.Split(f)
+
+ foundFiles = append(foundFiles, expandGoWildcard(dir)...)
+
+ continue
+ }
+
+ if _, err := os.Stat(f); err == nil {
+ foundFiles = append(foundFiles, f)
+ }
+ }
+
+ // Use relative path to print shorter names, sort out test foundFiles if chosen.
+ for _, f := range foundFiles {
+ if skipTests {
+ if strings.HasSuffix(f, "_test.go") {
+ continue
+ }
+ }
+
+ if relativePath, err := filepath.Rel(cwd, f); err == nil {
+ filteredFiles = append(filteredFiles, relativePath)
+
+ continue
+ }
+
+ filteredFiles = append(filteredFiles, f)
+ }
+
+ return filteredFiles
+}
+
+// expandGoWildcard path provided.
+func expandGoWildcard(root string) []string {
+ foundFiles := []string{}
+
+ _ = filepath.Walk(root, func(path string, info os.FileInfo, _ error) error {
+ // Only append go foundFiles.
+ if !strings.HasSuffix(info.Name(), ".go") {
+ return nil
+ }
+
+ foundFiles = append(foundFiles, path)
+
+ return nil
+ })
+
+ return foundFiles
+}
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/go.work b/vendor/github.com/ryancurrah/gomodguard/v2/go.work
new file mode 100644
index 00000000..63d63678
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/go.work
@@ -0,0 +1,6 @@
+go 1.25.0
+
+use (
+ .
+ ./cmd/gomodguard
+)
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/go.work.sum b/vendor/github.com/ryancurrah/gomodguard/v2/go.work.sum
new file mode 100644
index 00000000..fc90f0f3
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/go.work.sum
@@ -0,0 +1,8 @@
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
+golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
+golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
+golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw=
+golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/issue.go b/vendor/github.com/ryancurrah/gomodguard/v2/issue.go
new file mode 100644
index 00000000..d60fc3a8
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/issue.go
@@ -0,0 +1,20 @@
+package gomodguard
+
+import (
+ "fmt"
+ "go/token"
+)
+
+// Issue represents the result of one error.
+type Issue struct {
+ FileName string
+ LineNumber int
+ Position token.Position
+ Reason string
+}
+
+// String returns the filename, line
+// number and reason of a Issue.
+func (r *Issue) String() string {
+ return fmt.Sprintf("%s:%d:1 %s", r.FileName, r.LineNumber, r.Reason)
+}
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/matchers.go b/vendor/github.com/ryancurrah/gomodguard/v2/matchers.go
new file mode 100644
index 00000000..ae74b978
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/matchers.go
@@ -0,0 +1,77 @@
+package gomodguard
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+)
+
+// MatchType represents the type of matching to be performed for a module name.
+type MatchType string
+
+const (
+ // ExactMatch matches a module name exactly.
+ ExactMatch MatchType = "exact"
+ // PrefixMatch matches a module name by prefix.
+ PrefixMatch MatchType = "prefix"
+ // RegexMatch matches a module name by regex.
+ RegexMatch MatchType = "regex"
+)
+
+// Matcher interface for matching module names.
+type Matcher interface {
+ Match(moduleName string) bool
+}
+
+// ExactMatcher matches a module name exactly.
+type ExactMatcher struct {
+ Target string
+}
+
+func (m ExactMatcher) Match(moduleName string) bool {
+ return strings.TrimSpace(moduleName) == m.Target
+}
+
+// PrefixMatcher matches a module name by prefix.
+type PrefixMatcher struct {
+ Prefix string
+}
+
+// Match returns true if the moduleName starts with the Prefix, ignoring leading/trailing whitespace and case.
+func (m PrefixMatcher) Match(moduleName string) bool {
+ return strings.HasPrefix(strings.TrimSpace(strings.ToLower(moduleName)), strings.ToLower(m.Prefix))
+}
+
+// RegexMatcher matches a module name by regex.
+type RegexMatcher struct {
+ Regex *regexp.Regexp
+}
+
+func (m RegexMatcher) Match(moduleName string) bool {
+ if m.Regex == nil {
+ return false
+ }
+
+ return m.Regex.MatchString(strings.TrimSpace(moduleName))
+}
+
+// compileMatcher creates a Matcher based on the match type and pattern.
+//
+//nolint:ireturn // This factory intentionally returns the Matcher interface.
+func compileMatcher(matchType MatchType, pattern string) (Matcher, error) {
+ switch matchType {
+ case PrefixMatch:
+ return PrefixMatcher{Prefix: strings.TrimSpace(pattern)}, nil
+ case RegexMatch:
+ re, err := regexp.Compile(strings.TrimSpace(pattern))
+ if err != nil {
+ return nil, err
+ }
+
+ return RegexMatcher{Regex: re}, nil
+ case ExactMatch, "":
+ return ExactMatcher{Target: strings.TrimSpace(pattern)}, nil
+ default:
+ return nil, fmt.Errorf("unknown match-type %q for pattern %q", matchType, pattern)
+ }
+}
diff --git a/vendor/github.com/ryancurrah/gomodguard/v2/processor.go b/vendor/github.com/ryancurrah/gomodguard/v2/processor.go
new file mode 100644
index 00000000..82fa4c2d
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/v2/processor.go
@@ -0,0 +1,517 @@
+package gomodguard
+
+import (
+ "bytes"
+ "cmp"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "go/parser"
+ "go/token"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "slices"
+ "strings"
+
+ "golang.org/x/mod/modfile"
+)
+
+const (
+ goModFilename = "go.mod"
+ errReadingGoModFile = "unable to read module file %s: %w"
+ errParsingGoModFile = "unable to parse module file %s: %w"
+)
+
+var (
+ blockReasonInBlockedList = "import of package `%s` is blocked because the module is in the blocked modules list."
+ blockReasonHasLocalReplaceDirective = "import of package `%s` is blocked because the module has a local replace directive."
+
+ // startsWithVersion is used to test when a string begins with the version identifier of a module,
+ // after having stripped the prefix base module name. IE "github.com/foo/bar/v2/baz" => "v2/baz"
+ // probably indicates that the module is actually github.com/foo/bar/v2, not github.com/foo/bar.
+ startsWithVersion = regexp.MustCompile(`^v[0-9]+`)
+)
+
+// ruleIndex provides deterministic, specificity-based rule matching.
+// Rules are evaluated in three tiers:
+// 1. Exact match — O(1) map lookup.
+// 2. Prefix match — longest matching prefix wins.
+// 3. Regex match — evaluated in alphabetical key order; first match wins.
+type ruleIndex struct {
+ exactLookup map[string]string // trimmed module name -> original map key
+ prefixKeys []string // sorted by length desc, then alphabetically
+ regexKeys []string // sorted alphabetically
+ matchers map[string]Matcher // key -> compiled matcher
+}
+
+// newRuleIndex categorises rule keys into exact, prefix, and regex tiers
+// and pre-sorts the prefix and regex tiers for deterministic evaluation.
+func newRuleIndex(keys []string, matchTypes map[string]MatchType, matchers map[string]Matcher) *ruleIndex {
+ idx := &ruleIndex{
+ exactLookup: make(map[string]string, len(keys)),
+ matchers: matchers,
+ }
+
+ for _, k := range keys {
+ switch matchTypes[k] {
+ case ExactMatch:
+ idx.exactLookup[strings.TrimSpace(k)] = k
+ case PrefixMatch:
+ idx.prefixKeys = append(idx.prefixKeys, k)
+ case RegexMatch:
+ idx.regexKeys = append(idx.regexKeys, k)
+ default:
+ idx.exactLookup[strings.TrimSpace(k)] = k
+ }
+ }
+
+ // Longest prefix first for most-specific match.
+ slices.SortFunc(idx.prefixKeys, func(a, b string) int {
+ return cmp.Compare(len(b), len(a))
+ })
+
+ // Alphabetical order for deterministic regex evaluation.
+ slices.Sort(idx.regexKeys)
+
+ return idx
+}
+
+// bestMatch returns the key of the best-matching rule for moduleName,
+// following the tiered precedence: exact > longest prefix > first regex.
+func (idx *ruleIndex) bestMatch(moduleName string) (string, bool) {
+ trimmed := strings.TrimSpace(moduleName)
+
+ // Tier 1: exact match (O(1))
+ if key, ok := idx.exactLookup[trimmed]; ok {
+ return key, true
+ }
+
+ // Tier 2: longest prefix match
+ for _, key := range idx.prefixKeys {
+ if idx.matchers[key].Match(moduleName) {
+ return key, true
+ }
+ }
+
+ // Tier 3: first regex match (alphabetical order)
+ for _, key := range idx.regexKeys {
+ if idx.matchers[key].Match(moduleName) {
+ return key, true
+ }
+ }
+
+ return "", false
+}
+
+// Configuration of gomodguard allow and block lists.
+type Configuration struct {
+ Allowed Allowed `yaml:"allowed"`
+ Blocked Blocked `yaml:"blocked"`
+ LocalReplaceDirectives bool `yaml:"local_replace_directives"`
+}
+
+// InitMatchers initializes matchers for the configuration rules.
+func (c *Configuration) InitMatchers() error {
+ for i := range c.Allowed {
+ m, err := compileMatcher(c.Allowed[i].MatchType, c.Allowed[i].Module)
+ if err != nil {
+ return fmt.Errorf("failed compiling allowed matcher for '%s': %w", c.Allowed[i].Module, err)
+ }
+
+ c.Allowed[i].Matcher = m
+ }
+
+ for i := range c.Blocked {
+ m, err := compileMatcher(c.Blocked[i].MatchType, c.Blocked[i].Module)
+ if err != nil {
+ return fmt.Errorf("failed compiling blocked matcher for '%s': %w", c.Blocked[i].Module, err)
+ }
+
+ c.Blocked[i].Matcher = m
+ }
+
+ return nil
+}
+
+// Processor processes Go files.
+type Processor struct {
+ Config *Configuration
+ Modfile *modfile.File
+ blockedModulesFromModFile map[string][]string
+}
+
+// NewProcessor will create a Processor to lint blocked packages.
+func NewProcessor(config *Configuration) (*Processor, error) {
+ goModFileBytes, err := loadGoModFile()
+ if err != nil {
+ return nil, fmt.Errorf(errReadingGoModFile, goModFilename, err)
+ }
+
+ modFile, err := modfile.Parse(goModFilename, goModFileBytes, nil)
+ if err != nil {
+ return nil, fmt.Errorf(errParsingGoModFile, goModFilename, err)
+ }
+
+ if err := config.InitMatchers(); err != nil {
+ return nil, err
+ }
+
+ p := &Processor{
+ Config: config,
+ Modfile: modFile,
+ }
+
+ p.SetBlockedModules()
+
+ return p, nil
+}
+
+// ProcessFiles takes a string slice with file names (full paths)
+// and lints them.
+func (p *Processor) ProcessFiles(filenames []string) (issues []Issue) {
+ for _, filename := range filenames {
+ data, err := os.ReadFile(filepath.Clean(filename))
+ if err != nil {
+ issues = append(issues, Issue{
+ FileName: filename,
+ LineNumber: 0,
+ Reason: fmt.Sprintf("unable to read file, file cannot be linted (%s)", err.Error()),
+ })
+
+ continue
+ }
+
+ issues = append(issues, p.process(filename, data)...)
+ }
+
+ return issues
+}
+
+// SetBlockedModules determines and sets which modules are blocked by reading
+// the go.mod file of the current module.
+//
+// It works by iterating over the required modules specified in the require
+// directive, checking if the module prefix or full name is in the allowed list.
+//
+// Rules are evaluated using a layered strategy for deterministic results:
+// 1. Exact match — O(1) lookup; wins immediately.
+// 2. Prefix match — longest matching prefix wins.
+// 3. Regex match — evaluated in alphabetical key order; first match wins.
+func (p *Processor) SetBlockedModules() { //nolint:gocognit // Ack this is a long func.
+ blockedModules := make(map[string][]string, len(p.Modfile.Require))
+ currentModuleName := p.Modfile.Module.Mod.Path
+ requiredModules := p.Modfile.Require
+
+ // Build tiered rule indices for blocked and allowed rules.
+ blockedIdx, blockedLookup := buildRuleIndex(
+ p.Config.Blocked,
+ func(r BlockedModule) string { return r.Module },
+ func(r BlockedModule) MatchType { return r.MatchType },
+ func(r BlockedModule) Matcher { return r.Matcher },
+ )
+ allowedIdx, allowedLookup := buildRuleIndex(
+ p.Config.Allowed,
+ func(r AllowedModule) string { return r.Module },
+ func(r AllowedModule) MatchType { return r.MatchType },
+ func(r AllowedModule) Matcher { return r.Matcher },
+ )
+
+ for i := range requiredModules {
+ requiredModuleName := strings.TrimSpace(requiredModules[i].Mod.Path)
+ requiredModuleVersion := strings.TrimSpace(requiredModules[i].Mod.Version)
+
+ var matchedBlockRule *BlockedModule
+
+ // Check against blocked rules first (exact > longest prefix > first regex)
+ if key, ok := blockedIdx.bestMatch(requiredModuleName); ok {
+ rule := blockedLookup[key] // copy
+ matchedBlockRule = &rule
+ }
+
+ if matchedBlockRule != nil && matchedBlockRule.IsCurrentModuleARecommendation(currentModuleName) {
+ // The current module is a recommended alternative for this blocked module, allowing it.
+ matchedBlockRule = nil
+ }
+
+ if matchedBlockRule != nil {
+ isVersBlocked, err := matchedBlockRule.CheckVersion(requiredModuleVersion)
+ if err != nil {
+ // NOTE: Unreachable via real go.mod files; modfile.Parse rejects invalid versions
+ // earlier. Left untested by design as this branch cannot be triggered.
+ blockedModules[requiredModuleName] = append(blockedModules[requiredModuleName],
+ fmt.Sprintf("%s unable to parse version `%s`: %s",
+ blockReasonInBlockedList, requiredModuleVersion, err,
+ ),
+ )
+
+ continue
+ }
+
+ if !isVersBlocked {
+ // Doesn't match the blocked version constraint, so we let it pass the block check
+ matchedBlockRule = nil
+ }
+ }
+
+ // If it's blocked, record it and move to next
+ if matchedBlockRule != nil {
+ blockedModules[requiredModuleName] = append(blockedModules[requiredModuleName],
+ fmt.Sprintf("%s %s", blockReasonInBlockedList,
+ matchedBlockRule.BlockReason(requiredModuleVersion),
+ ),
+ )
+
+ continue
+ }
+
+ // If no allowed list is specified, default mapping is to allow all
+ if len(p.Config.Allowed) == 0 {
+ continue
+ }
+
+ isAllowed := false
+
+ var matchedButWrongVersion *AllowedModule
+
+ if key, ok := allowedIdx.bestMatch(requiredModuleName); ok {
+ rule := allowedLookup[key] // copy
+
+ ok, err := rule.CheckVersion(requiredModuleVersion)
+
+ switch {
+ case err != nil:
+ // NOTE: Unreachable via real go.mod files; modfile.Parse rejects invalid versions
+ // earlier. Left untested by design as this branch cannot be triggered.
+ blockedModules[requiredModuleName] = append(blockedModules[requiredModuleName],
+ fmt.Sprintf("import of package `%%s` is blocked because the module version `%s` could not be parsed: %s",
+ requiredModuleVersion, err,
+ ),
+ )
+
+ isAllowed = true // skip the generic "not allowed" message below
+ case ok:
+ isAllowed = true
+ default:
+ matchedButWrongVersion = &rule
+ }
+ }
+
+ if !isAllowed {
+ blockedModules[requiredModuleName] = append(blockedModules[requiredModuleName],
+ fmt.Sprintf("import of package `%%s` is blocked because %s", matchedButWrongVersion.NotAllowedReason(requiredModuleVersion)))
+ }
+ }
+
+ // Blocks local 'replace' directives to prevent committing dev overrides.
+ // Legitimate sibling modules in multi-module repos (sharing the same
+ // module name) are exempt.
+ if p.Config.LocalReplaceDirectives {
+ for _, r := range p.Modfile.Replace {
+ if isBlockedLocalReplace(r) {
+ blockedModules[r.Old.Path] = append(blockedModules[r.Old.Path],
+ blockReasonHasLocalReplaceDirective,
+ )
+ }
+ }
+ }
+
+ p.blockedModulesFromModFile = blockedModules
+}
+
+// buildRuleIndex constructs a ruleIndex and a key→rule lookup from any slice of rules.
+// The three accessor functions extract the module name, match type, and compiled matcher
+// from each rule, keeping this function independent of the concrete rule type.
+func buildRuleIndex[R any](
+ rules []R,
+ moduleFn func(R) string,
+ matchTypeFn func(R) MatchType,
+ matcherFn func(R) Matcher,
+) (*ruleIndex, map[string]R) {
+ keys := make([]string, 0, len(rules))
+ matchTypes := make(map[string]MatchType, len(rules))
+ matchers := make(map[string]Matcher, len(rules))
+ lookup := make(map[string]R, len(rules))
+
+ for _, r := range rules {
+ mod := moduleFn(r)
+ keys = append(keys, mod)
+ matchTypes[mod] = matchTypeFn(r)
+ matchers[mod] = matcherFn(r)
+ lookup[mod] = r
+ }
+
+ return newRuleIndex(keys, matchTypes, matchers), lookup
+}
+
+// process file imports and add lint error if blocked package is imported.
+func (p *Processor) process(filename string, data []byte) (issues []Issue) {
+ fileSet := token.NewFileSet()
+
+ file, err := parser.ParseFile(fileSet, filename, data, parser.ParseComments)
+ if err != nil {
+ issues = append(issues, Issue{
+ FileName: filename,
+ LineNumber: 0,
+ Reason: fmt.Sprintf("invalid syntax, file cannot be linted (%s)", err.Error()),
+ })
+
+ return
+ }
+
+ imports := file.Imports
+ for n := range imports {
+ importedPkg := strings.TrimSpace(strings.Trim(imports[n].Path.Value, "\""))
+
+ blockReasons := p.isBlockedPackageFromModFile(importedPkg)
+ if blockReasons == nil {
+ continue
+ }
+
+ for _, blockReason := range blockReasons {
+ issues = append(issues, p.addError(fileSet, imports[n].Pos(), blockReason))
+ }
+ }
+
+ return issues
+}
+
+// addError adds an error for the file and line number for the current token.Pos
+// with the given reason.
+func (p *Processor) addError(fileset *token.FileSet, pos token.Pos, reason string) Issue {
+ position := fileset.Position(pos)
+
+ return Issue{
+ FileName: position.Filename,
+ LineNumber: position.Line,
+ Position: position,
+ Reason: reason,
+ }
+}
+
+// isBlockedPackageFromModFile returns the block reason if the package is blocked.
+func (p *Processor) isBlockedPackageFromModFile(packageName string) []string {
+ for blockedModuleName, blockReasons := range p.blockedModulesFromModFile {
+ if isPackageInModule(packageName, blockedModuleName) {
+ formattedReasons := make([]string, 0, len(blockReasons))
+
+ for _, blockReason := range blockReasons {
+ formattedReasons = append(formattedReasons, fmt.Sprintf(blockReason, packageName))
+ }
+
+ return formattedReasons
+ }
+ }
+
+ return nil
+}
+
+// loadGoModFile loads the contents of the go.mod file in the current working directory.
+// It first checks the "GOMOD" environment variable to determine the path of the go.mod file.
+// If the environment variable is not set or the file does not exist, it falls back to reading the go.mod file in the current directory.
+// If the "GOMOD" environment variable is set to "/dev/null", it returns an error indicating that the current working directory must have a go.mod file.
+// The function returns the contents of the go.mod file as a byte slice and any error encountered during the process.
+func loadGoModFile() ([]byte, error) {
+ cmd := exec.Command("go", "env", "-json") //nolint:noctx // Ack at some point might use os/exec.CommandContext.
+ stdout, _ := cmd.StdoutPipe()
+ _ = cmd.Start()
+
+ if stdout == nil {
+ return os.ReadFile(filepath.Clean(goModFilename))
+ }
+
+ buf := new(bytes.Buffer)
+ _, _ = buf.ReadFrom(stdout)
+
+ goEnv := make(map[string]string)
+
+ err := json.Unmarshal(buf.Bytes(), &goEnv)
+ if err != nil {
+ return os.ReadFile(goModFilename)
+ }
+
+ if _, ok := goEnv["GOMOD"]; !ok {
+ return os.ReadFile(goModFilename)
+ }
+
+ if _, err = os.Stat(goEnv["GOMOD"]); os.IsNotExist(err) {
+ return os.ReadFile(goModFilename)
+ }
+
+ if goEnv["GOMOD"] == "/dev/null" || goEnv["GOMOD"] == "NUL" {
+ return nil, errors.New("current working directory must have a go.mod file")
+ }
+
+ return os.ReadFile(goEnv["GOMOD"])
+}
+
+// isBlockedLocalReplace returns true if the replace directive points to a local
+// filesystem path that is not a legitimate sibling module.
+func isBlockedLocalReplace(r *modfile.Replace) bool {
+ if r.New.Path == "" || r.New.Version != "" {
+ return false
+ }
+
+ replacePath := r.New.Path
+ if !filepath.IsAbs(replacePath) {
+ wd, err := os.Getwd()
+ if err != nil {
+ wd = "."
+ }
+
+ replacePath = filepath.Join(wd, replacePath)
+ }
+
+ return !isModuleAtPath(replacePath, r.Old.Path)
+}
+
+// isModuleAtPath returns true if the directory at path contains a go.mod file
+// that declares moduleName as its module, indicating a legitimate sibling module
+// in a multi-module repository rather than a local development override.
+func isModuleAtPath(path, moduleName string) bool {
+ data, err := os.ReadFile(filepath.Clean(filepath.Join(path, goModFilename)))
+ if err != nil {
+ return false
+ }
+
+ mf, err := modfile.Parse(goModFilename, data, nil)
+ if err != nil {
+ return false
+ }
+
+ return mf.Module.Mod.Path == moduleName
+}
+
+// isPackageInModule determines if a package is a part of the specified Go module.
+func isPackageInModule(pkg, mod string) bool {
+ // Split pkg and mod paths into parts
+ pkgPart := strings.Split(pkg, "/")
+ modPart := strings.Split(mod, "/")
+
+ pkgPartMatches := 0
+
+ // Count number of times pkg path matches the mod path
+ for i, m := range modPart {
+ if len(pkgPart) > i && pkgPart[i] == m {
+ pkgPartMatches++
+ }
+ }
+
+ // If pkgPartMatches are not the same length as modPart
+ // than the package is not in this module
+ if pkgPartMatches != len(modPart) {
+ return false
+ }
+
+ if len(pkgPart) > len(modPart) {
+ // If pkgPart path starts with a major version
+ // than the package is not in this module as
+ // major versions are completely different modules
+ if startsWithVersion.MatchString(pkgPart[len(modPart)]) {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/.golangci.yml b/vendor/github.com/santhosh-tekuri/jsonschema/v6/.golangci.yml
index 6534d531..94a3eca3 100644
--- a/vendor/github.com/santhosh-tekuri/jsonschema/v6/.golangci.yml
+++ b/vendor/github.com/santhosh-tekuri/jsonschema/v6/.golangci.yml
@@ -1,4 +1,3 @@
-version: "2"
linters:
enable:
- nakedret
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/.swp b/vendor/github.com/santhosh-tekuri/jsonschema/v6/.swp
deleted file mode 100644
index e5119003..00000000
Binary files a/vendor/github.com/santhosh-tekuri/jsonschema/v6/.swp and /dev/null differ
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/format.go b/vendor/github.com/santhosh-tekuri/jsonschema/v6/format.go
index b78b22e2..0d7f5903 100644
--- a/vendor/github.com/santhosh-tekuri/jsonschema/v6/format.go
+++ b/vendor/github.com/santhosh-tekuri/jsonschema/v6/format.go
@@ -318,7 +318,7 @@ func validateEmail(v any) error {
return LocalizableError("local part more than 64 characters long")
}
- if len(local) > 1 && strings.HasPrefix(local, `"`) && strings.HasPrefix(local, `"`) {
+ if len(local) > 1 && strings.HasPrefix(local, `"`) && strings.HasSuffix(local, `"`) {
// quoted
local := local[1 : len(local)-1]
if strings.IndexByte(local, '\\') != -1 || strings.IndexByte(local, '"') != -1 {
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/go.work.sum b/vendor/github.com/santhosh-tekuri/jsonschema/v6/go.work.sum
index 2b5b811d..c268feb5 100644
--- a/vendor/github.com/santhosh-tekuri/jsonschema/v6/go.work.sum
+++ b/vendor/github.com/santhosh-tekuri/jsonschema/v6/go.work.sum
@@ -1,4 +1,4 @@
-github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
+github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/kind/kind.go b/vendor/github.com/santhosh-tekuri/jsonschema/v6/kind/kind.go
index a37fb0b9..62efa755 100644
--- a/vendor/github.com/santhosh-tekuri/jsonschema/v6/kind/kind.go
+++ b/vendor/github.com/santhosh-tekuri/jsonschema/v6/kind/kind.go
@@ -511,7 +511,7 @@ func (*ContentMediaType) KeywordPath() []string {
}
func (k *ContentMediaType) LocalizedString(p *message.Printer) string {
- return p.Sprintf("value if not of mediatype %s: %v", quote(k.Want), k.Err)
+ return p.Sprintf("value is not of mediatype %s: %v", quote(k.Want), k.Err)
}
// --
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/objcompiler.go b/vendor/github.com/santhosh-tekuri/jsonschema/v6/objcompiler.go
index f1494b13..d47efa89 100644
--- a/vendor/github.com/santhosh-tekuri/jsonschema/v6/objcompiler.go
+++ b/vendor/github.com/santhosh-tekuri/jsonschema/v6/objcompiler.go
@@ -355,9 +355,13 @@ func (c *objCompiler) enqueueRef(pname string) (*Schema, error) {
if ref == nil {
return nil, nil
}
+ return c.enqueueRefVal(*ref)
+}
+
+func (c *objCompiler) enqueueRefVal(ref string) (*Schema, error) {
baseURL := c.res.id
// baseURL := c.r.baseURL(c.up.ptr)
- uf, err := baseURL.join(*ref)
+ uf, err := baseURL.join(ref)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/schema.go b/vendor/github.com/santhosh-tekuri/jsonschema/v6/schema.go
index b4c1f37a..ab2474fa 100644
--- a/vendor/github.com/santhosh-tekuri/jsonschema/v6/schema.go
+++ b/vendor/github.com/santhosh-tekuri/jsonschema/v6/schema.go
@@ -1,8 +1,25 @@
+/*
+Package jsonschema provides json-schema compilation and validation.
+
+The schema is compiled against the version specified in "$schema" property.
+If "$schema" property is missing, it uses latest draft which currently implemented
+by this library.
+
+You can force to use specific draft, when "$schema" is missing, as follows:
+
+ compiler := jsonschema.NewCompiler()
+ compiler.DefaultDraft(jsonschema.Draft4)
+
+This package supports loading json-schema from filePath and fileURL.
+
+see examples for usage.
+*/
package jsonschema
import (
"encoding/json"
"fmt"
+ "math"
"math/big"
)
@@ -110,12 +127,22 @@ const (
)
func typeOf(v any) jsonType {
- switch v.(type) {
+ switch v := v.(type) {
case nil:
return nullType
case bool:
return booleanType
- case json.Number, float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
+ case float64:
+ if math.IsNaN(v) || math.IsInf(v, 0) {
+ return invalidType
+ }
+ return numberType
+ case float32:
+ if math.IsNaN(float64(v)) || math.IsInf(float64(v), 0) {
+ return invalidType
+ }
+ return numberType
+ case json.Number, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
return numberType
case string:
return stringType
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/util.go b/vendor/github.com/santhosh-tekuri/jsonschema/v6/util.go
index c6f8e775..8cd32aae 100644
--- a/vendor/github.com/santhosh-tekuri/jsonschema/v6/util.go
+++ b/vendor/github.com/santhosh-tekuri/jsonschema/v6/util.go
@@ -320,6 +320,9 @@ func equals(v1, v2 any) (bool, ErrorKind) {
v2, ok := v2.(string)
return ok && v1 == v2, nil
case json.Number, float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
+ if typeOf(v2) != numberType {
+ return false, nil
+ }
num1, ok1 := new(big.Rat).SetString(fmt.Sprint(v1))
num2, ok2 := new(big.Rat).SetString(fmt.Sprint(v2))
return ok1 && ok2 && num1.Cmp(num2) == 0, nil
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/validator.go b/vendor/github.com/santhosh-tekuri/jsonschema/v6/validator.go
index e2ace37a..53a4c730 100644
--- a/vendor/github.com/santhosh-tekuri/jsonschema/v6/validator.go
+++ b/vendor/github.com/santhosh-tekuri/jsonschema/v6/validator.go
@@ -293,6 +293,7 @@ func (vd *validator) objValidate(obj map[string]any) {
}
if err := sch.validate(pname, vd.regexpEngine, meta, resources, vd.assertVocabs, vd.vocabularies); err != nil {
verr := err.(*ValidationError)
+ verr.InstanceLocation = vd.vloc
verr.SchemaURL = s.PropertyNames.Location
verr.ErrorKind = &kind.PropertyNames{Property: pname}
vd.addErr(verr)
@@ -375,7 +376,7 @@ func (vd *validator) arrValidate(arr []any) {
}
case *Schema:
for i, item := range arr[evaluated:] {
- vd.addErr(vd.validateVal(additional, item, strconv.Itoa(i)))
+ vd.addErr(vd.validateVal(additional, item, strconv.Itoa(evaluated+i)))
}
}
}
@@ -390,7 +391,7 @@ func (vd *validator) arrValidate(arr []any) {
// items2020 --
if s.Items2020 != nil {
for i, item := range arr[evaluated:] {
- vd.addErr(vd.validateVal(s.Items2020, item, strconv.Itoa(i)))
+ vd.addErr(vd.validateVal(s.Items2020, item, strconv.Itoa(evaluated+i)))
}
}
}
@@ -503,6 +504,7 @@ func (vd *validator) strValidate(str string) {
}
if err = sch.validate(*deserialized, vd.regexpEngine, meta, resources, vd.assertVocabs, vd.vocabularies); err != nil {
verr := err.(*ValidationError)
+ verr.InstanceLocation = vd.vloc
verr.SchemaURL = s.Location
verr.ErrorKind = &kind.ContentSchema{}
vd.addErr(verr)
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v6/vocab.go b/vendor/github.com/santhosh-tekuri/jsonschema/v6/vocab.go
index c81cb700..eaed8c95 100644
--- a/vendor/github.com/santhosh-tekuri/jsonschema/v6/vocab.go
+++ b/vendor/github.com/santhosh-tekuri/jsonschema/v6/vocab.go
@@ -14,6 +14,10 @@ func (ctx *CompilerContext) Enqueue(schPath []string) *Schema {
return ctx.c.enqueuePtr(ptr)
}
+func (ctx *CompilerContext) EnqueueRef(ref string) (*Schema, error) {
+ return ctx.c.enqueueRefVal(ref)
+}
+
// Vocabulary defines a set of keywords, their syntax and
// their semantics.
type Vocabulary struct {
diff --git a/vendor/github.com/securego/gosec/v2/.env.example b/vendor/github.com/securego/gosec/v2/.env.example
new file mode 100644
index 00000000..0a7ec71e
--- /dev/null
+++ b/vendor/github.com/securego/gosec/v2/.env.example
@@ -0,0 +1,3 @@
+GOSEC_AI_API_KEY=your_ai_api_key
+GOSEC_AI_PROVIDER=atlas
+GOSEC_AI_BASE_URL=https://api.atlascloud.ai/v1
diff --git a/vendor/github.com/securego/gosec/v2/.gitignore b/vendor/github.com/securego/gosec/v2/.gitignore
index d9f5c1fc..eac8f99d 100644
--- a/vendor/github.com/securego/gosec/v2/.gitignore
+++ b/vendor/github.com/securego/gosec/v2/.gitignore
@@ -33,10 +33,12 @@ coverage.out
*.prof
.DS_Store
+.env.local
+.env.*.local
.vscode
.idea
# SBOMs generated during CI
/bom.json
-1
\ No newline at end of file
+1
diff --git a/vendor/github.com/securego/gosec/v2/CLAUDE.md b/vendor/github.com/securego/gosec/v2/CLAUDE.md
new file mode 100644
index 00000000..f3e0b72d
--- /dev/null
+++ b/vendor/github.com/securego/gosec/v2/CLAUDE.md
@@ -0,0 +1,51 @@
+# gosec - Go Security Checker
+
+gosec is a Go static analysis tool that inspects Go source code for security vulnerabilities by scanning the Go AST and SSA form.
+
+## Build & Test
+
+```bash
+# Build
+go build ./cmd/gosec/
+
+# Run all tests
+go test ./...
+
+# Run a specific test
+go test -run TestName ./path/to/package/
+
+# Lint
+golangci-lint run
+
+# Run gosec against a sample file
+go run ./cmd/gosec/ ./path/to/sample.go
+```
+
+## Code Style
+
+- Idiomatic Go; follow existing patterns in the codebase.
+- Prefer SSA-based analyzers over AST-based rules when feasible.
+- Optimize for performance — avoid unnecessary repeated AST or SSA traversals.
+
+## Project Structure
+
+- `rules/` — AST-based rule implementations
+- `analyzers/` — SSA-based analyzer implementations
+- `cmd/gosec/` — CLI entry point
+- `testutils/` — sample files used in tests (positive and negative cases)
+- `issue/` — issue and CWE type definitions
+- `report/` — output formatters
+
+## Adding Rules
+
+- Select an appropriate CWE aligned with current repository mappings.
+- Integrate the rule in all required registration points.
+- Add sample files in `testutils/` with at least 2 positive and 2 negative cases.
+- Update rule documentation in `README.md` in the same style as other rules.
+
+## Custom Commands
+
+- `/create-gosec-rule` — Design and implement a new gosec rule from an issue description
+- `/fix-gosec-bug` — Investigate and fix a bug from a GitHub issue URL
+- `/update-go-versions` — Bump supported Go versions across the repo
+- `/update-action-version` — Update the gosec GHCR image version in action.yml
diff --git a/vendor/github.com/securego/gosec/v2/DEVELOPMENT.md b/vendor/github.com/securego/gosec/v2/DEVELOPMENT.md
index f32526d5..5a8a0e3c 100644
--- a/vendor/github.com/securego/gosec/v2/DEVELOPMENT.md
+++ b/vendor/github.com/securego/gosec/v2/DEVELOPMENT.md
@@ -97,7 +97,7 @@ func runMyAnalyzer(pass *analysis.Pass) (interface{}, error) {
### Creating taint analysis rules
gosec taint analyzers track data flow from untrusted sources to dangerous sinks.
-Current taint rules include SQL injection, command injection, path traversal, SSRF, XSS, log injection, and SMTP injection.
+Current taint rules include SQL injection, command injection, path traversal, SSRF, XSS, log injection, SMTP injection, server-side template injection, unsafe deserialization, and open redirect.
#### Steps
diff --git a/vendor/github.com/securego/gosec/v2/Makefile b/vendor/github.com/securego/gosec/v2/Makefile
index 6dd8c4c3..f91529ca 100644
--- a/vendor/github.com/securego/gosec/v2/Makefile
+++ b/vendor/github.com/securego/gosec/v2/Makefile
@@ -33,6 +33,9 @@ install-govulncheck:
test: build-race fmt vet sec govulncheck
go run github.com/onsi/ginkgo/v2/ginkgo -- --ginkgo.v --ginkgo.fail-fast
+test-nocache: build-race fmt vet sec govulncheck
+ go test -count=1 -v ./...
+
fmt:
@echo "FORMATTING"
@FORMATTED=`$(GO) fmt ./...`
@@ -99,4 +102,4 @@ tlsconfig:
perf-diff:
./perf-diff.sh
-.PHONY: test build clean release image image-push tlsconfig perf-diff
+.PHONY: test test-nocache build clean release image image-push tlsconfig perf-diff
diff --git a/vendor/github.com/securego/gosec/v2/README.md b/vendor/github.com/securego/gosec/v2/README.md
index 6f6d27d1..c3362fa9 100644
--- a/vendor/github.com/securego/gosec/v2/README.md
+++ b/vendor/github.com/securego/gosec/v2/README.md
@@ -1,7 +1,8 @@
# gosec - Go Security Checker
-Inspects source code for security problems by scanning the Go AST and SSA code representation.
+Inspects source code for security problems by scanning the Go AST
+and SSA code representation.
@@ -14,20 +15,23 @@ Inspects source code for security problems by scanning the Go AST and SSA code r
- [Selecting rules](#selecting-rules)
- [Output formats](#output-formats)
-> ⚠️ Container image migration notice: `gosec` images was migrated from Docker Hub to `ghcr.io/securego/gosec`.
-> Starting with release `v2.24.7` the image is no longer published in Docker Hub.
-
## Features
-- **Pattern-based rules** for detecting common security issues in Go code
-- **SSA-based analyzers** for type conversions, slice bounds, and crypto issues
-- **Taint analysis** for tracking data flow from user input to dangerous functions (SQL injection, command injection, path traversal, SSRF, XSS, log injection)
+- **Pattern-based rules** for detecting common security issues
+ in Go code
+- **SSA-based analyzers** for type conversions, slice bounds,
+ and crypto issues
+- **Taint analysis** for tracking data flow from user input to
+ dangerous functions (SQL injection, command injection, path
+ traversal, SSRF, XSS, log injection, SMTP injection, SSTI,
+ unsafe deserialization, open redirect)
## License
Licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License.
-You may obtain a copy of the License [here](http://www.apache.org/licenses/LICENSE-2.0).
+You may obtain a copy of the License
+[here](http://www.apache.org/licenses/LICENSE-2.0).
## Project status
@@ -48,7 +52,8 @@ You may obtain a copy of the License [here](http://www.apache.org/licenses/LICEN
You can run `gosec` as a GitHub action as follows:
-Use the versioned tag with `@master` which is pinned to the latest stable release. This will provide a stable behavior.
+Use the versioned tag with `@master` which is pinned to the
+latest stable release. This will provide a stable behavior.
```yaml
name: Run Gosec
@@ -75,10 +80,16 @@ jobs:
#### Scanning Projects with Private Modules
-If your project imports private Go modules, you need to configure authentication so that `gosec` can fetch the dependencies. Set the following environment variables in your workflow:
+If your project imports private Go modules, you need to
+configure authentication so that `gosec` can fetch the
+dependencies. Set the following environment variables in
+your workflow:
-- `GOPRIVATE`: A comma-separated list of module path prefixes that should be considered private (e.g., `github.com/your-org/*`).
-- `GITHUB_AUTHENTICATION_TOKEN`: A GitHub token with read access to your private repositories.
+- `GOPRIVATE`: A comma-separated list of module path prefixes
+ that should be considered private
+ (e.g., `github.com/your-org/*`).
+- `GITHUB_AUTHENTICATION_TOKEN`: A GitHub token with read
+ access to your private repositories.
```yaml
name: Run Gosec
@@ -107,9 +118,13 @@ jobs:
### Integrating with code scanning
-You can [integrate third-party code analysis tools](https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/integrating-with-code-scanning) with GitHub code scanning by uploading data as SARIF files.
+You can [integrate third-party code analysis tools](https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/integrating-with-code-scanning)
+with GitHub code scanning by uploading data as SARIF files.
-The workflow shows an example of running the `gosec` as a step in a GitHub action workflow which outputs the `results.sarif` file. The workflow then uploads the `results.sarif` file to GitHub using the `upload-sarif` action.
+The workflow shows an example of running the `gosec` as a step
+in a GitHub action workflow which outputs the `results.sarif`
+file. The workflow then uploads the `results.sarif` file to
+GitHub using the `upload-sarif` action.
```yaml
name: "Security Scan"
@@ -143,7 +158,12 @@ jobs:
### Go Analysis
-The `goanalysis` package provides a [`golang.org/x/tools/go/analysis.Analyzer`](https://pkg.go.dev/golang.org/x/tools/go/analysis) for integration with tools that support the standard Go analysis interface, such as Bazel's [nogo](https://github.com/bazelbuild/rules_go/blob/master/go/nogo.rst) framework:
+The `goanalysis` package provides a
+[`golang.org/x/tools/go/analysis.Analyzer`](https://pkg.go.dev/golang.org/x/tools/go/analysis)
+for integration with tools that support the standard Go
+analysis interface, such as Bazel's
+[nogo](https://github.com/bazelbuild/rules_go/blob/master/go/nogo.rst)
+framework:
```starlark
nogo(
@@ -185,34 +205,48 @@ gosec -fmt sarif -out results.sarif ./...
## Usage
-Gosec can be configured to only run a subset of rules, to exclude certain file
-paths, and produce reports in different formats. By default all rules will be
-run against the supplied input files. To recursively scan from the current
-directory you can supply `./...` as the input argument.
+Gosec can be configured to only run a subset of rules, to
+exclude certain file paths, and produce reports in different
+formats. By default all rules will be run against the supplied
+input files. To recursively scan from the current directory you
+can supply `./...` as the input argument.
### Available rules
gosec includes rules across these categories:
-- `G1xx`: general secure coding issues (for example hardcoded credentials, unsafe usage, HTTP hardening)
-- `G2xx`: injection risks in query/template/command construction
-- `G3xx`: file and path handling risks (permissions, traversal, temp files, archive extraction)
+- `G1xx`: general secure coding issues (for example hardcoded
+ credentials, unsafe usage, HTTP hardening, cookie security)
+- `G2xx`: injection risks in query/template/command
+ construction
+- `G3xx`: file and path handling risks (permissions, traversal,
+ temp files, archive extraction)
- `G4xx`: crypto and TLS weaknesses
- `G5xx`: blocklisted imports
-- `G6xx`: Go-specific correctness/security checks (for example range aliasing and slice bounds)
-- `G7xx`: taint analysis rules (SQL injection, command injection, path traversal, SSRF, XSS, log and SMTP injection)
+- `G6xx`: Go-specific correctness/security checks (for example
+ range aliasing and slice bounds)
+- `G7xx`: taint analysis rules (SQL injection, command
+ injection, path traversal, SSRF, XSS, log, SMTP injection,
+ SSTI, unsafe deserialization, and open redirect)
-For the full list, rule descriptions, and per-rule configuration, see [RULES.md](RULES.md).
+For the full list, rule descriptions, and per-rule
+configuration, see [RULES.md](RULES.md).
### Retired rules
-- G105: Audit the use of math/big.Int.Exp - [CVE is fixed](https://github.com/golang/go/issues/15184)
-- G307: Deferring a method which returns an error - causing more inconvenience than fixing a security issue, despite the details from this [blog post](https://www.joeshaw.org/dont-defer-close-on-writable-files/)
+- G105: Audit the use of math/big.Int.Exp -
+ [CVE is fixed](https://github.com/golang/go/issues/15184)
+- G307: Deferring a method which returns an error - causing
+ more inconvenience than fixing a security issue, despite the
+ details from this
+ [blog post](https://www.joeshaw.org/dont-defer-close-on-writable-files/)
### Selecting rules
-By default, gosec will run all rules against the supplied file paths. It is however possible to select a subset of rules to run via the `-include=` flag,
-or to specify a set of rules to explicitly exclude using the `-exclude=` flag.
+By default, gosec will run all rules against the supplied file
+paths. It is however possible to select a subset of rules to
+run via the `-include=` flag, or to specify a set of rules to
+explicitly exclude using the `-exclude=` flag.
```bash
# Run a specific set of rules
@@ -224,11 +258,16 @@ $ gosec -exclude=G303 ./...
### CWE Mapping
-Every issue detected by `gosec` is mapped to a [CWE (Common Weakness Enumeration)](http://cwe.mitre.org/data/index.html) which describes in more generic terms the vulnerability. The exact mapping can be found [here](https://github.com/securego/gosec/blob/master/issue/issue.go#L50).
+Every issue detected by `gosec` is mapped to a
+[CWE (Common Weakness Enumeration)](http://cwe.mitre.org/data/index.html)
+which describes in more generic terms the vulnerability. The
+exact mapping can be found
+[here](https://github.com/securego/gosec/blob/master/issue/issue.go#L50).
### Configuration
-A number of global settings can be provided in a configuration file as follows:
+A number of global settings can be provided in a configuration
+file as follows:
```JSON
{
@@ -239,8 +278,10 @@ A number of global settings can be provided in a configuration file as follows:
}
```
-- `nosec`: this setting will overwrite all `#nosec` directives defined throughout the code base
-- `audit`: runs in audit mode which enables addition checks that for normal code analysis might be too nosy
+- `nosec`: this setting will overwrite all `#nosec` directives
+ defined throughout the code base
+- `audit`: runs in audit mode which enables addition checks
+ that for normal code analysis might be too nosy
```bash
# Run with a global configuration file
@@ -249,9 +290,9 @@ $ gosec -conf config.json .
### Path-Based Rule Exclusions
-Large repositories with multiple components may need different security rules
-for different paths. Use `exclude-rules` to suppress specific rules for specific
-paths.
+Large repositories with multiple components may need different
+security rules for different paths. Use `exclude-rules` to
+suppress specific rules for specific paths.
**Configuration File:**
```json
@@ -283,22 +324,31 @@ gosec --exclude-rules="cmd/.*:G204,G304;test/.*:G101" ./...
| Field | Type | Description |
|-------|------|-------------|
-| `path` | string (regex) | Regular expression matched against file paths |
-| `rules` | []string | Rule IDs to exclude. Use `*` to exclude all rules |
+| `path` | string (regex) | Regex matched against file paths |
+| `rules` | []string | Rule IDs to exclude. `*` for all |
#### Rule Configuration
-Some rules accept configuration flags as well; these flags are documented in [RULES.md](https://github.com/securego/gosec/blob/master/RULES.md).
+Some rules accept configuration flags as well; these flags are
+documented in
+[RULES.md](https://github.com/securego/gosec/blob/master/RULES.md).
#### Go version
-Some rules require a specific Go version which is retrieved from the Go module file present in the project. If this version cannot be found, it will fallback to Go runtime version.
+Some rules require a specific Go version which is retrieved
+from the Go module file present in the project. If this version
+cannot be found, it will fallback to Go runtime version.
-The Go module version is parsed using the `go list` command which in some cases might lead to performance degradation. In this situation, the go module version can be easily provided by setting the environment variable `GOSECGOVERSION=go1.21.1`.
+The Go module version is parsed using the `go list` command
+which in some cases might lead to performance degradation. In
+this situation, the go module version can be easily provided by
+setting the environment variable
+`GOSECGOVERSION=go1.21.1`.
### Dependencies
-gosec loads packages using Go modules. In most projects, dependencies are resolved automatically during scanning.
+gosec loads packages using Go modules. In most projects,
+dependencies are resolved automatically during scanning.
If dependencies are missing, run:
@@ -309,9 +359,11 @@ go mod download
### Excluding test files and folders
-gosec will ignore test files across all packages and any dependencies in your vendor directory.
+gosec will ignore test files across all packages and any
+dependencies in your vendor directory.
-The scanning of test files can be enabled with the following flag:
+The scanning of test files can be enabled with the following
+flag:
```bash
gosec -tests ./...
@@ -325,7 +377,8 @@ Also additional folders can be excluded as follows:
### Excluding generated files
-gosec can ignore generated go files with default generated code comment.
+gosec can ignore generated go files with default generated
+code comment.
```
// Code generated by some generator DO NOT EDIT.
@@ -337,36 +390,83 @@ gosec -exclude-generated ./...
### Auto fixing vulnerabilities
-gosec can suggest fixes based on AI recommendation. It will call an AI API to receive a suggestion for a security finding.
-
-You can enable this feature by providing the following command line arguments:
-
-- `ai-api-provider`: the name of the AI API provider. Supported providers:
- - **Gemini**: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.5-flash-lite`, `gemini-2.0-flash`, `gemini-2.0-flash-lite` (default)
- - **Claude**: `claude-sonnet-4-0` (default), `claude-opus-4-0`, `claude-opus-4-1`, `claude-sonnet-3-7`
- - **OpenAI**: `gpt-4o` (default), `gpt-4o-mini`
- - **Custom OpenAI-compatible**: Any custom model name (requires `ai-base-url`)
-- `ai-api-key` or set the environment variable `GOSEC_AI_API_KEY`: the key to access the AI API
- - For Gemini, you can create an API key following [these instructions](https://ai.google.dev/gemini-api/docs/api-key)
- - For Claude, get your API key from [Anthropic Console](https://console.anthropic.com/)
- - For OpenAI, get your API key from [OpenAI Platform](https://platform.openai.com/api-keys)
-- `ai-base-url`: (optional) custom base URL for OpenAI-compatible APIs (e.g., Azure OpenAI, LocalAI, Ollama)
-- `ai-skip-ssl`: (optional) skip SSL certificate verification for AI API (useful for self-signed certificates)
+gosec can suggest fixes based on AI recommendation. It will
+call an AI API to receive a suggestion for a security finding.
+
+You can enable this feature by providing the following command
+line arguments:
+
+- `ai-api-provider`: the name of the AI API provider.
+ Supported providers:
+ - **Atlas Cloud**: `atlas` (default model
+ `deepseek-ai/deepseek-v4-flash`),
+ `atlas-deepseek-v4-flash`,
+ `atlas-qwen3-coder-next`, `atlas-kimi-k2.6`, or
+ `atlas:` for any Atlas Cloud hosted chat model.
+ Atlas Cloud is an OpenAI-compatible provider available at
+ [atlascloud.ai](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=gosec)
+ - **Gemini**: `gemini-3-pro-preview` (default),
+ `gemini-2.5-pro`, `gemini-2.5-flash`,
+ `gemini-2.5-flash-lite`
+ - **Claude**: `claude-sonnet-4-6` (default),
+ `claude-opus-4-7`, `claude-opus-4-6`,
+ `claude-sonnet-4-5`, `claude-opus-4-5`,
+ `claude-haiku-4-5`
+ - **OpenAI**: `gpt-5.4` (default), `gpt-5.4-mini`,
+ `gpt-5.4-nano`
+ - **Custom OpenAI-compatible**: Any custom model name
+ (requires `ai-base-url`)
+- `ai-api-key` or set the environment variable
+ `GOSEC_AI_API_KEY`: the key to access the AI API
+ - For Gemini, you can create an API key following
+ [these instructions](https://ai.google.dev/gemini-api/docs/api-key)
+ - For Claude, get your API key from
+ [Anthropic Console](https://console.anthropic.com/)
+ - For OpenAI, get your API key from
+ [OpenAI Platform](https://platform.openai.com/api-keys)
+- `ai-base-url`: (optional) custom base URL for
+ OpenAI-compatible APIs (e.g., Azure OpenAI, LocalAI,
+ Ollama)
+ - Atlas Cloud uses `https://api.atlascloud.ai/v1` by default,
+ so `ai-base-url` is optional for the built-in `atlas`
+ provider
+- `GOSEC_AI_PROVIDER`: (optional) environment variable
+ alternative to `ai-api-provider`
+- `GOSEC_AI_BASE_URL`: (optional) environment variable
+ alternative to `ai-base-url`
+- `ai-skip-ssl`: (optional) skip SSL certificate verification
+ for AI API (useful for self-signed certificates)
+
+> 🎁 **[Atlas Cloud](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=gosec)** is a full-modal AI inference platform that gives developers a single AI API to access video generation, image generation, and LLM APIs. Instead of managing multiple vendor integrations, you connect once and get unified access to 300+ curated models across all modalities.
+>
+> Check out Atlas Cloud's new coding plan promotion for more budget-friendly API access: [https://www.atlascloud.ai/console/coding-plan](https://www.atlascloud.ai/console/coding-plan)
**Examples:**
```bash
+# Using Atlas Cloud with the default DeepSeek V4 Flash model
+export GOSEC_AI_API_KEY="your_key"
+export GOSEC_AI_PROVIDER="atlas"
+gosec ./...
+
+# Using Atlas Cloud with an explicit hosted model
+GOSEC_AI_API_KEY="your_key" \
+ gosec -ai-api-provider="atlas:qwen/qwen3-coder-next" ./...
+
# Using Gemini
-gosec -ai-api-provider="gemini-2.0-flash" -ai-api-key="your_key" ./...
+gosec -ai-api-provider="gemini-3-pro-preview" \
+ -ai-api-key="your_key" ./...
# Using Claude
-gosec -ai-api-provider="claude-sonnet-4-0" -ai-api-key="your_key" ./...
+gosec -ai-api-provider="claude-sonnet-4-6" \
+ -ai-api-key="your_key" ./...
# Using OpenAI
-gosec -ai-api-provider="gpt-4o" -ai-api-key="your_key" ./...
+gosec -ai-api-provider="gpt-5.4" \
+ -ai-api-key="your_key" ./...
# Using Azure OpenAI
-gosec -ai-api-provider="gpt-4o" \
+gosec -ai-api-provider="gpt-5.4" \
-ai-api-key="your_azure_key" \
-ai-base-url="https://your-resource.openai.azure.com/openai/deployments/your-deployment" \
./...
@@ -386,13 +486,16 @@ gosec -ai-api-provider="custom-model" \
### Annotating code
-As with all automated detection tools, there will be cases of false positives.
-In cases where gosec reports a failure that has been manually verified as being safe,
-it is possible to annotate the code with a comment that starts with `#nosec`.
+As with all automated detection tools, there will be cases of
+false positives. In cases where gosec reports a failure that
+has been manually verified as being safe, it is possible to
+annotate the code with a comment that starts with `#nosec`.
-The `#nosec` comment should have the format `#nosec [RuleList] [- Justification]`.
+The `#nosec` comment should have the format
+`#nosec [RuleList] [-- Justification]`.
-The `#nosec` comment needs to be placed on the line where the warning is reported.
+The `#nosec` comment needs to be placed on the line where the
+warning is reported.
```go
func main() {
@@ -410,51 +513,92 @@ func main() {
}
```
-When a specific false positive has been identified and verified as safe, you may
-wish to suppress only that single rule (or a specific set of rules) within a section of code,
-while continuing to scan for other problems. To do this, you can list the rule(s) to be suppressed within
-the `#nosec` annotation, e.g: `/* #nosec G401 */` or `//#nosec G201 G202 G203`
+When a specific false positive has been identified and verified
+as safe, you may wish to suppress only that single rule (or a
+specific set of rules) within a section of code, while
+continuing to scan for other problems. To do this, you can list
+the rule(s) to be suppressed within the `#nosec` annotation,
+e.g: `/* #nosec G401 */` or `//#nosec G201 G202 G203`
-You could put the description or justification text for the annotation. The
-justification should be after the rule(s) to suppress and start with two or
-more dashes, e.g: `//#nosec G101 G102 -- This is a false positive`
+You could put the description or justification text for the
+annotation. The justification should be after the rule(s) to
+suppress and start with two or more dashes,
+e.g: `//#nosec G101 G102 -- This is a false positive`
-Alternatively, gosec also supports the `//gosec:disable` directive, which functions similar to `#nosec`:
+Alternatively, gosec also supports the `//gosec:disable`
+directive, which functions similar to `#nosec`:
```go
//gosec:disable G101 -- This is a false positive
```
-In some cases you may also want to revisit places where `#nosec` or `//gosec:disable` annotations
-have been used. To run the scanner and ignore any `#nosec` annotations you
-can do the following:
+In some cases you may also want to revisit places where
+`#nosec` or `//gosec:disable` annotations have been used. To
+run the scanner and ignore any `#nosec` annotations you can do
+the following:
```bash
gosec -nosec=true ./...
```
+#### Requiring rule IDs and justifications
+
+To prevent annotations from inadvertently suppressing unrelated
+rules, or from being added without explanation, gosec accepts
+two opt-in flags. Both default to `false`, so existing
+codebases keep working unchanged.
+
+- `-nosec-require-rules` rejects naked `#nosec` /
+ `//gosec:disable` directives that do not list any rule ID.
+- `-nosec-require-justification` rejects directives that do
+ not carry a `-- justification` after the rule list.
+
+When enabled, a directive that fails the check no longer
+suppresses any finding and is reported as an error in the
+output, alongside any underlying issue on the line.
+
+```bash
+gosec -nosec-require-rules -nosec-require-justification ./...
+```
+
+The same options can be set via the global config block:
+
+```json
+{
+ "global": {
+ "nosec-require-rules": "enabled",
+ "nosec-require-justification": "enabled"
+ }
+}
+```
+
### Tracking suppressions
-As described above, we could suppress violations externally (using `-include`/
-`-exclude`) or inline (using `#nosec` annotations). Suppression metadata can be emitted for auditing.
+As described above, we could suppress violations externally
+(using `-include`/`-exclude`) or inline (using `#nosec`
+annotations). Suppression metadata can be emitted for auditing.
Enable suppression tracking with `-track-suppressions`:
```bash
-gosec -track-suppressions -exclude=G101 -fmt=sarif -out=results.sarif ./...
+gosec -track-suppressions -exclude=G101 \
+ -fmt=sarif -out=results.sarif ./...
```
-- For external suppressions, gosec records suppression info where `kind` is
-`external` and `justification` is `Globally suppressed.`.
-- For inline suppressions, gosec records suppression info where `kind` is
-`inSource` and `justification` is the text after two or more dashes in the
-comment.
+- For external suppressions, gosec records suppression info
+ where `kind` is `external` and `justification` is
+ `Globally suppressed.`.
+- For inline suppressions, gosec records suppression info
+ where `kind` is `inSource` and `justification` is the text
+ after two or more dashes in the comment.
-**Note:** Only SARIF and JSON formats support tracking suppressions.
+**Note:** Only SARIF and JSON formats support tracking
+suppressions.
### Build tags
-gosec is able to pass your [Go build tags](https://pkg.go.dev/go/build/) to the analyzer.
+gosec is able to pass your
+[Go build tags](https://pkg.go.dev/go/build/) to the analyzer.
They can be provided as a comma separated list as follows:
```bash
@@ -463,9 +607,12 @@ gosec -tags debug,ignore ./...
### Output formats
-gosec supports `text`, `json`, `yaml`, `csv`, `junit-xml`, `html`, `sonarqube`, `golint`, and `sarif`. By default,
-results will be reported to stdout, but can also be written to an output
-file. The output format is controlled by the `-fmt` flag, and the output file is controlled by the `-out` flag as follows:
+gosec supports `text`, `json`, `yaml`, `csv`, `junit-xml`,
+`html`, `sonarqube`, `golint`, and `sarif`. By default,
+results will be reported to stdout, but can also be written to
+an output file. The output format is controlled by the `-fmt`
+flag, and the output file is controlled by the `-out` flag as
+follows:
```bash
# Write output in json format to results.json
@@ -473,16 +620,22 @@ $ gosec -fmt=json -out=results.json *.go
```
Use `-stdout` to print results while also writing `-out`.
-Use `-verbose` to override stdout format while preserving the file format.
+Use `-verbose` to override stdout format while preserving the
+file format.
```bash
# Write output in json format to results.json as well as stdout
$ gosec -fmt=json -out=results.json -stdout *.go
-# Overrides the output format to 'text' when stdout the results, while writing it to results.json
+# Overrides the output format to 'text' when stdout the results,
+# while writing it to results.json
$ gosec -fmt=json -out=results.json -stdout -verbose=text *.go
```
-**Note:** gosec generates the [generic issue import format](https://docs.sonarqube.org/latest/analysis/generic-issue/) for SonarQube, and a report has to be imported into SonarQube using `sonar.externalIssuesReportPaths=path/to/gosec-report.json`.
+**Note:** gosec generates the
+[generic issue import format](https://docs.sonarqube.org/latest/analysis/generic-issue/)
+for SonarQube, and a report has to be imported into SonarQube
+using
+`sonar.externalIssuesReportPaths=path/to/gosec-report.json`.
## Common usage patterns
@@ -505,7 +658,8 @@ gosec -tests ./...
## Development
-Development documentation was moved to [DEVELOPMENT.md](DEVELOPMENT.md).
+Development documentation was moved to
+[DEVELOPMENT.md](DEVELOPMENT.md).
## Who is using gosec?
@@ -513,6 +667,7 @@ This is a [list](USERS.md) with some of the gosec's users.
## Sponsors
-Support this project by becoming a sponsor. Your logo will show up here with a link to your website
+Support this project by becoming a sponsor. Your logo will
+show up here with a link to your website
diff --git a/vendor/github.com/securego/gosec/v2/RULES.md b/vendor/github.com/securego/gosec/v2/RULES.md
index 21994ce1..badc3b18 100644
--- a/vendor/github.com/securego/gosec/v2/RULES.md
+++ b/vendor/github.com/securego/gosec/v2/RULES.md
@@ -16,6 +16,7 @@
- [G104](#g104)
- [G111](#g111)
- [G117](#g117)
+ - [G118](#g118)
- [G301, G302, G306, G307](#g301-g302-g306-g307)
## Rules List
@@ -38,12 +39,13 @@
- G115 — Type conversion which leads to integer overflow (**SSA**)
- G116 — Detect Trojan Source attacks using bidirectional Unicode characters (**AST**)
- [G117](#g117) — Potential exposure of secrets via JSON/YAML/XML/TOML marshaling (**AST**)
-- G118 — Context propagation failure leading to goroutine/resource leaks (**SSA**)
+- [G118](#g118) — Context propagation failure leading to goroutine/resource leaks (**SSA**)
- G119 — Unsafe redirect policy may propagate sensitive headers (**SSA**)
-- G120 — Unbounded form parsing in HTTP handlers can cause memory exhaustion (**SSA**)
+- G120 — Unbounded `ParseMultipartForm` in HTTP handlers can cause memory exhaustion (**Taint**)
- G121 — Unsafe CrossOriginProtection bypass patterns (**SSA**)
- G122 — Filesystem TOCTOU race risk in `filepath.Walk/WalkDir` callbacks (**SSA**)
- G123 — TLS resumption may bypass `VerifyPeerCertificate` when `VerifyConnection` is unset (**SSA**)
+- G124 — Insecure HTTP cookie configuration missing Secure, HttpOnly, or SameSite attributes (**SSA**)
### G2xx: Injection Patterns
@@ -97,6 +99,9 @@
- G705 — XSS via taint analysis (**Taint**)
- G706 — Log injection via taint analysis (**Taint**)
- G707 — SMTP command/header injection via taint analysis (**Taint**)
+- G708 — Server-side template injection via `text/template` (**Taint**)
+- G709 — Unsafe deserialization of untrusted data (**Taint**)
+- G710 — Open redirect via taint analysis (**Taint**)
_Note: Implementation types used in this document:_
- **AST**: rule implemented in `rules/` and evaluated on AST patterns
@@ -170,6 +175,106 @@ This replaces the default pattern.
}
```
+### G118
+
+`G118` detects three classes of context-propagation failure using SSA-level analysis:
+
+**1. Lost cancel function (CWE-400)**
+
+Reports when a `context.WithCancel`, `context.WithTimeout`, or `context.WithDeadline` call
+returns a cancel function that is never called, potentially leaking resources.
+
+```go
+// Flagged: cancel never called
+func work(ctx context.Context) {
+ child, _ := context.WithTimeout(ctx, time.Second)
+ _ = child
+}
+
+// Safe: cancel deferred
+func work(ctx context.Context) {
+ child, cancel := context.WithTimeout(ctx, time.Second)
+ defer cancel()
+ _ = child
+}
+```
+
+The following patterns are all recognised as *safe* (cancel is considered called):
+
+| Pattern | Description |
+|---|---|
+| `defer cancel()` | Direct deferred call |
+| `defer func() { cancel() }()` | Cancel in a deferred closure |
+| `cancelCopy := cancel; defer cancelCopy()` | Alias via variable |
+| `return ctx, cancel` | Cancel returned to caller (responsibility transferred) |
+| `s.cancelFn = cancel` + method `s.cancelFn()` | Stored in struct field, called via receiver method |
+| `s.cancel = cancel; defer s.cancel()` | Stored in struct field, deferred in same function |
+| `s.cancel = cancel; defer func() { s.cancel() }()` | Stored in struct field, called in closure |
+| Struct containing field is returned | Caller inherits cancel responsibility |
+| `var cancel CancelFunc` in `init()` + `cancel()` in another function | Package-level variable assigned in init, called in any function (e.g., signal handlers) |
+
+Example of package-level variable pattern:
+
+```go
+// Safe: cancel stored in package-level variable and called in signal handler
+var cancel context.CancelFunc
+
+func init() {
+ ctx, c := context.WithCancel(context.Background())
+ cancel = c
+}
+
+func handleShutdown() {
+ cancel() // Called from signal handler
+}
+```
+
+**2. Goroutine uses `context.Background`/`TODO` when request context is available (CWE-400)**
+
+Reports when a goroutine spawned inside an HTTP handler or a function accepting a
+`context.Context` / `*http.Request` uses `context.Background()` or `context.TODO()`
+instead of the request-scoped context.
+
+```go
+// Flagged
+func handler(w http.ResponseWriter, r *http.Request) {
+ go func() {
+ ctx := context.Background() // ignores request context
+ doWork(ctx)
+ }()
+}
+```
+
+**3. Long-running loop without `ctx.Done()` guard (CWE-400)**
+
+Reports an infinite loop that performs blocking I/O (e.g. `http.Get`, `db.Query`,
+`time.Sleep`, interface methods such as `Read`/`Write`) but never checks `ctx.Done()`,
+making the loop impossible to cancel.
+
+```go
+// Flagged
+func poll(ctx context.Context) {
+ for {
+ http.Get("https://example.com") // blocks, no cancellation path
+ time.Sleep(time.Second)
+ }
+}
+
+// Safe
+func poll(ctx context.Context) {
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case <-time.After(time.Second):
+ http.Get("https://example.com")
+ }
+ }
+}
+```
+
+Loops with an external exit path (e.g. a `break` or bounded `for i < n`) are not flagged.
+
### G301, G302, G306, G307
File and directory permission rules can be configured with stricter maximum permissions:
diff --git a/vendor/github.com/securego/gosec/v2/action.yml b/vendor/github.com/securego/gosec/v2/action.yml
index dce57794..62848c71 100644
--- a/vendor/github.com/securego/gosec/v2/action.yml
+++ b/vendor/github.com/securego/gosec/v2/action.yml
@@ -10,7 +10,7 @@ inputs:
runs:
using: "docker"
- image: "docker://ghcr.io/securego/gosec:2.24.7"
+ image: "docker://ghcr.io/securego/gosec@sha256:d0859f242774504d57b17442b2dc77d4ffd2f4d30fbdf92c7eb612b2a394f477" # 2.27.1
args:
- ${{ inputs.args }}
diff --git a/vendor/github.com/securego/gosec/v2/analyzer.go b/vendor/github.com/securego/gosec/v2/analyzer.go
index ed03efc6..0276cff8 100644
--- a/vendor/github.com/securego/gosec/v2/analyzer.go
+++ b/vendor/github.com/securego/gosec/v2/analyzer.go
@@ -29,6 +29,7 @@ import (
"path"
"path/filepath"
"reflect"
+ "regexp"
"runtime/debug"
"strconv"
"strings"
@@ -711,6 +712,9 @@ func (gosec *Analyzer) buildSSA(pkg *packages.Package) (*buildssa.SSA, error) {
if pkg.TypesInfo == nil {
return nil, fmt.Errorf("%w: %s", ErrNoPackageTypeInfo, pkg.Name)
}
+ if pkg.IllTyped {
+ return nil, fmt.Errorf("package %s has type errors, skipping SSA analysis", pkg.Name)
+ }
pass := &analysis.Pass{
Fset: pkg.Fset,
Files: pkg.Syntax,
@@ -758,20 +762,24 @@ func ParseErrors(pkg *packages.Package) (map[string][]Error, error) {
return nil, nil
}
errs := make(map[string][]Error)
+ posRegexp := regexp.MustCompile(`^(.*?)(?::(\w+))?(?::(\w+))?$`)
for _, pkgErr := range pkg.Errors {
- parts := strings.Split(pkgErr.Pos, ":")
- file := parts[0]
+ matches := posRegexp.FindStringSubmatch(pkgErr.Pos)
+ file := pkgErr.Pos
var err error
- var line int
- if len(parts) > 1 {
- if line, err = strconv.Atoi(parts[1]); err != nil {
- return nil, fmt.Errorf("parsing line: %w", err)
+ var line, column int
+ if len(matches) > 0 {
+ file = matches[1]
+ file = strings.TrimSuffix(file, ":")
+ if len(matches) > 2 && matches[2] != "" {
+ if line, err = strconv.Atoi(matches[2]); err != nil {
+ return nil, fmt.Errorf("parsing line: %w", err)
+ }
}
- }
- var column int
- if len(parts) > 2 {
- if column, err = strconv.Atoi(parts[2]); err != nil {
- return nil, fmt.Errorf("parsing column: %w", err)
+ if len(matches) > 3 && matches[3] != "" {
+ if column, err = strconv.Atoi(matches[3]); err != nil {
+ return nil, fmt.Errorf("parsing column: %w", err)
+ }
}
}
msg := strings.TrimSpace(pkgErr.Msg)
@@ -797,6 +805,13 @@ func (gosec *Analyzer) AppendError(file string, err error) {
gosec.errors[file] = errors
}
+// appendErrorAt appends an error tied to a specific source location.
+func (gosec *Analyzer) appendErrorAt(file string, line, column int, err error) {
+ errs := gosec.errors[file]
+ errs = append(errs, *NewError(line, column, err.Error()))
+ gosec.errors[file] = errs
+}
+
// findNoSecDirective checks if the comment group contains `#nosec` or `//gosec:disable` directive.
// If found, it returns true and the directive's arguments.
func findNoSecDirective(group *ast.CommentGroup, noSecDefaultTag, noSecAlternativeTag string) (bool, string) {
@@ -960,6 +975,9 @@ func (v *astVisitor) ignore(n ast.Node) (map[string]issue.SuppressionInfo, *ast.
noSecAlternativeTag = NoSecTag(noSecAlternativeTag)
}
+ requireRules, _ := v.gosec.config.IsGlobalEnabled(NoSecRequireRules)
+ requireJustification, _ := v.gosec.config.IsGlobalEnabled(NoSecRequireJustification)
+
for _, group := range groups {
found, args := findNoSecDirective(group, noSecDefaultTag, noSecAlternativeTag)
if !found {
@@ -968,49 +986,57 @@ func (v *astVisitor) ignore(n ast.Node) (map[string]issue.SuppressionInfo, *ast.
v.stats.NumNosec++
justification := ""
+ hasJustificationDelim := false
if idx := strings.Index(args, "--"); idx > -1 {
+ hasJustificationDelim = true
justification = strings.TrimSpace(strings.TrimLeft(args[idx+2:], "-"))
args = args[:idx]
}
directive := strings.TrimSpace(args)
- // If the directive is empty or contains "block" (legacy), ignore all rules
- if len(directive) == 0 || directive == "block" {
- return map[string]issue.SuppressionInfo{
- aliasOfAllRules: {
- Kind: "inSource",
- Justification: justification,
- },
- }, group
- }
-
ignores := make(map[string]issue.SuppressionInfo)
suppression := issue.SuppressionInfo{
Kind: "inSource",
Justification: justification,
}
- // Manually parse identifiers starting with 'G' followed by 3 digits
- for i := 0; i < len(directive); {
- if directive[i] == 'G' && i+4 <= len(directive) {
- ruleID := directive[i : i+4]
- valid := true
- for j := 1; j < 4; j++ {
- if directive[i+j] < '0' || directive[i+j] > '9' {
- valid = false
- break
+ // Manually parse identifiers starting with 'G' followed by 3 digits.
+ // A directive that is empty or equals the legacy "block" keyword
+ // suppresses all rules.
+ if len(directive) != 0 && directive != "block" {
+ for i := 0; i < len(directive); {
+ if directive[i] == 'G' && i+4 <= len(directive) {
+ ruleID := directive[i : i+4]
+ valid := true
+ for j := 1; j < 4; j++ {
+ if directive[i+j] < '0' || directive[i+j] > '9' {
+ valid = false
+ break
+ }
+ }
+ if valid {
+ ignores[ruleID] = suppression
+ i += 4
+ continue
}
}
- if valid {
- ignores[ruleID] = suppression
- i += 4
- continue
- }
+ i++
}
- i++
}
- if len(ignores) == 0 {
+ naked := len(ignores) == 0
+ justificationMissing := !hasJustificationDelim || justification == ""
+
+ if requireRules && naked {
+ v.reportInvalidDirective(group, "missing rule ID (e.g. G401); naked #nosec / //gosec:disable is disallowed by -nosec-require-rules")
+ continue
+ }
+ if requireJustification && justificationMissing {
+ v.reportInvalidDirective(group, "missing justification (expected `-- `); required by -nosec-require-justification")
+ continue
+ }
+
+ if naked {
ignores[aliasOfAllRules] = suppression
}
return ignores, group
@@ -1018,6 +1044,18 @@ func (v *astVisitor) ignore(n ast.Node) (map[string]issue.SuppressionInfo, *ast.
return nil, nil
}
+// reportInvalidDirective records an error for a malformed nosec directive so
+// it surfaces in reports without suppressing any findings.
+func (v *astVisitor) reportInvalidDirective(group *ast.CommentGroup, reason string) {
+ tokFile := v.context.FileSet.File(group.Pos())
+ if tokFile == nil {
+ return
+ }
+ pos := tokFile.Position(group.Pos())
+ v.gosec.appendErrorAt(tokFile.Name(), pos.Line, pos.Column,
+ fmt.Errorf("invalid nosec directive: %s", reason))
+}
+
// updateIssues updates the issues list with the given issue, handling suppressions.
func (gosec *Analyzer) updateIssues(issue *issue.Issue, issues []*issue.Issue, stats *Metrics, allIgnores ignores) []*issue.Issue {
if issue != nil {
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/analyzerslist.go b/vendor/github.com/securego/gosec/v2/analyzers/analyzerslist.go
index 658b30a1..0a541e90 100644
--- a/vendor/github.com/securego/gosec/v2/analyzers/analyzerslist.go
+++ b/vendor/github.com/securego/gosec/v2/analyzers/analyzerslist.go
@@ -81,6 +81,34 @@ var (
Severity: "HIGH",
CWE: "CWE-93",
}
+
+ SSTIRule = taint.RuleInfo{
+ ID: "G708",
+ Description: "Server-side template injection via text/template",
+ Severity: "CRITICAL",
+ CWE: "CWE-94",
+ }
+
+ UnsafeDeserializationRule = taint.RuleInfo{
+ ID: "G709",
+ Description: "Unsafe deserialization of untrusted data",
+ Severity: "HIGH",
+ CWE: "CWE-502",
+ }
+
+ OpenRedirectRule = taint.RuleInfo{
+ ID: "G710",
+ Description: "Open redirect: user-controlled URL flows into http.Redirect",
+ Severity: "MEDIUM",
+ CWE: "CWE-601",
+ }
+
+ FormParsingLimitRule = taint.RuleInfo{
+ ID: "G120",
+ Description: "Unbounded multipart form parsing can cause memory exhaustion",
+ Severity: "MEDIUM",
+ CWE: "CWE-400",
+ }
)
// AnalyzerList contains a mapping of analyzer ID's to analyzer definitions and a mapping
@@ -128,6 +156,7 @@ var defaultAnalyzers = []AnalyzerDefinition{
{"G121", "Unsafe CrossOriginProtection bypass patterns", newCORSBypassPatternAnalyzer},
{"G122", "Filesystem TOCTOU race risk in filepath.Walk/WalkDir callbacks", newWalkSymlinkRaceAnalyzer},
{"G123", "TLS resumption may bypass VerifyPeerCertificate when VerifyConnection is unset", newTLSResumptionVerifyPeerAnalyzer},
+ {"G124", "Insecure HTTP cookie configuration missing Secure, HttpOnly, or SameSite attributes", newInsecureCookieAnalyzer},
{"G602", "Possible slice bounds out of range", newSliceBoundsAnalyzer},
{"G407", "Use of hardcoded IV/nonce for encryption", newHardCodedNonce},
{"G408", "Stateful misuse of ssh.PublicKeyCallback leading to auth bypass", newSSHCallbackAnalyzer},
@@ -138,6 +167,9 @@ var defaultAnalyzers = []AnalyzerDefinition{
{"G705", "XSS via taint analysis", newXSSAnalyzer},
{"G706", "Log injection via taint analysis", newLogInjectionAnalyzer},
{"G707", "SMTP command/header injection via taint analysis", newSMTPInjectionAnalyzer},
+ {"G708", "Server-side template injection via taint analysis", newSSTIAnalyzer},
+ {"G709", "Unsafe deserialization of untrusted data via taint analysis", newUnsafeDeserializationAnalyzer},
+ {"G710", "Open redirect via taint analysis", newOpenRedirectAnalyzer},
}
// Generate the list of analyzers to use
@@ -172,6 +204,10 @@ func DefaultTaintAnalyzers() []*analysis.Analyzer {
xssConfig := XSS()
logConfig := LogInjection()
smtpConfig := SMTPInjection()
+ sstiConfig := SSTI()
+ deserConfig := UnsafeDeserialization()
+ formConfig := FormParsingLimits()
+ openRedirectConfig := OpenRedirect()
return []*analysis.Analyzer{
taint.NewGosecAnalyzer(&SQLInjectionRule, &sqlConfig),
@@ -181,5 +217,9 @@ func DefaultTaintAnalyzers() []*analysis.Analyzer {
taint.NewGosecAnalyzer(&XSSRule, &xssConfig),
taint.NewGosecAnalyzer(&LogInjectionRule, &logConfig),
taint.NewGosecAnalyzer(&SMTPInjectionRule, &smtpConfig),
+ taint.NewGosecAnalyzer(&SSTIRule, &sstiConfig),
+ taint.NewGosecAnalyzer(&UnsafeDeserializationRule, &deserConfig),
+ taint.NewGosecAnalyzer(&FormParsingLimitRule, &formConfig),
+ taint.NewGosecAnalyzer(&OpenRedirectRule, &openRedirectConfig),
}
}
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/context_propagation.go b/vendor/github.com/securego/gosec/v2/analyzers/context_propagation.go
index 0136d660..e5eee616 100644
--- a/vendor/github.com/securego/gosec/v2/analyzers/context_propagation.go
+++ b/vendor/github.com/securego/gosec/v2/analyzers/context_propagation.go
@@ -710,8 +710,40 @@ func isCancelCalled(cancelValue ssa.Value, allFuncs []*ssa.Function) bool {
if isStructFieldReturnedFromFunc(fa) {
return true
}
+ // Check if any function (including closures capturing the
+ // struct) loads and calls the same field. This handles
+ // post-construction storage such as:
+ // s.cancel = cancel; defer s.cancel()
+ // s.cancel = cancel; defer func() { s.cancel() }()
+ if isFieldCalledInAnyFunc(fa, allFuncs) {
+ return true
+ }
+ }
+ // Check if storing to a package-level global variable.
+ // When cancel is stored to a global (e.g., in init()), we need
+ // to search all functions in the package for loads of that global
+ // followed by a call.
+ if global, ok := r.Addr.(*ssa.Global); ok {
+ if isGlobalCalledInAnyFunc(global, allFuncs) {
+ return true
+ }
+ }
+ // Cancel stored into a slice/array element (e.g.
+ // `defers = append(defers, cancel)`, which lowers to a Store
+ // into the variadic array). The cancel escapes into a
+ // collection whose iteration sites are not reliably traceable
+ // in SSA — treat as a transfer of responsibility, mirroring
+ // the global/returned-field handling above.
+ if _, ok := r.Addr.(*ssa.IndexAddr); ok {
+ return true
}
queue = append(queue, r.Addr)
+ case *ssa.MapUpdate:
+ // Cancel stored as a map value (e.g.
+ // `cleanups[key] = cancel`). Same reasoning as IndexAddr.
+ if r.Value == current {
+ return true
+ }
case *ssa.UnOp:
if r.Op == token.MUL && r.X == current {
queue = append(queue, r)
@@ -783,6 +815,163 @@ func isStructFieldReturnedFromFunc(fa *ssa.FieldAddr) bool {
return false
}
+// isFieldCalledInAnyFunc checks whether a cancel function stored into a struct
+// field is subsequently called in any function (including closures) that
+// accesses the same field by struct pointer type and field index. This covers
+// post-construction storage patterns not handled by isCancelCalledViaStructField:
+//
+// s.cancel = cancel; defer s.cancel()
+// s.cancel = cancel; defer func() { s.cancel() }()
+func isFieldCalledInAnyFunc(fa *ssa.FieldAddr, allFuncs []*ssa.Function) bool {
+ structPtrType := fa.X.Type()
+ fieldIdx := fa.Field
+
+ for _, fn := range allFuncs {
+ if fn == nil {
+ continue
+ }
+ for _, block := range fn.Blocks {
+ for _, instr := range block.Instrs {
+ otherFA, ok := instr.(*ssa.FieldAddr)
+ if !ok || otherFA.Field != fieldIdx {
+ continue
+ }
+ if !types.Identical(otherFA.X.Type(), structPtrType) {
+ continue
+ }
+ if isFieldValueCalled(otherFA) {
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
+
+// isGlobalCalledInAnyFunc checks whether a cancel function stored into a
+// package-level global variable is subsequently called in any function
+// (including init(), main(), signal handlers, etc.). This handles patterns
+// like:
+//
+// var cancel context.CancelFunc
+// func init() { _, cancel = context.WithCancel(ctx) }
+// func shutdown() { cancel() }
+func isGlobalCalledInAnyFunc(global *ssa.Global, allFuncs []*ssa.Function) bool {
+ if global == nil {
+ return false
+ }
+
+ // Iterate through all functions in the package to find loads from this global
+ for _, fn := range allFuncs {
+ if fn == nil || fn.Blocks == nil {
+ continue
+ }
+
+ for _, block := range fn.Blocks {
+ for _, instr := range block.Instrs {
+ // Look for UnOp (dereference/load) from the global
+ unop, ok := instr.(*ssa.UnOp)
+ if !ok || unop.Op != token.MUL {
+ continue
+ }
+
+ // Check if this load is from our global
+ if unop.X != global {
+ continue
+ }
+
+ // Check if the loaded value is eventually called
+ if isValueCalled(unop) {
+ return true
+ }
+ }
+ }
+ }
+
+ return false
+}
+
+// isValueCalled checks if a value (typically a loaded function pointer) is
+// eventually used as a callee. This performs a BFS through value referrers
+// to find calls, handling phi nodes, stores/loads, type conversions, and closures.
+func isValueCalled(value ssa.Value) bool {
+ if value == nil {
+ return false
+ }
+
+ refs := value.Referrers()
+ if refs == nil {
+ return false
+ }
+
+ queue := []ssa.Value{value}
+ visited := make(map[ssa.Value]bool)
+
+ for len(queue) > 0 {
+ cur := queue[0]
+ queue = queue[1:]
+
+ if cur == nil || visited[cur] {
+ continue
+ }
+ visited[cur] = true
+
+ curRefs := cur.Referrers()
+ if curRefs == nil {
+ continue
+ }
+
+ for _, ref := range *curRefs {
+ switch r := ref.(type) {
+ case ssa.CallInstruction:
+ // Check if cur is used as the callee or an argument
+ if isUsedInCall(r.Common(), cur) {
+ return true
+ }
+ case *ssa.Phi:
+ // Value flows through phi node - continue tracking
+ queue = append(queue, r)
+ case *ssa.Store:
+ // Stored then loaded elsewhere - follow the address
+ if r.Val == cur {
+ queue = append(queue, r.Addr)
+ }
+ case *ssa.UnOp:
+ // Dereference or other operation - continue tracking
+ if r.X == cur {
+ queue = append(queue, r)
+ }
+ case *ssa.ChangeType:
+ // Type conversion - continue tracking
+ if r.X == cur {
+ queue = append(queue, r)
+ }
+ case *ssa.Convert:
+ // Type conversion - continue tracking
+ if r.X == cur {
+ queue = append(queue, r)
+ }
+ case *ssa.MakeInterface:
+ // Wrapped in interface - continue tracking
+ if r.X == cur {
+ queue = append(queue, r)
+ }
+ case *ssa.MakeClosure:
+ // Captured in closure - follow into closure body
+ if fn, ok := r.Fn.(*ssa.Function); ok {
+ for i, binding := range r.Bindings {
+ if binding == cur && i < len(fn.FreeVars) {
+ queue = append(queue, fn.FreeVars[i])
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false
+}
+
// isCancelCalledViaStructField checks whether a cancel function stored into a
// struct field (e.g., job.cancelFn = cancel) is subsequently called in any other
// method of the same receiver type (e.g., job.Close() calls job.cancelFn()).
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/conversion_overflow.go b/vendor/github.com/securego/gosec/v2/analyzers/conversion_overflow.go
index 23a350b4..2c3c7d86 100644
--- a/vendor/github.com/securego/gosec/v2/analyzers/conversion_overflow.go
+++ b/vendor/github.com/securego/gosec/v2/analyzers/conversion_overflow.go
@@ -79,6 +79,13 @@ func runConversionOverflow(pass *analysis.Pass) (any, error) {
continue
}
+ // Skip conversions between platform-word-sized
+ // types (e.g. uintptr -> int) since they never
+ // truncate bits.
+ if isSameWidthPlatformConversion(instr.X.Type(), instr.Type()) {
+ continue
+ }
+
if hasOverflow(srcInfo, dstInfo) {
if state.isSafeConversion(instr, dstInfo) {
continue
@@ -140,6 +147,28 @@ func hasOverflow(srcInfo, dstInfo IntTypeInfo) bool {
return srcInfo.Min < dstInfo.Min || srcInfo.Max > dstInfo.Max
}
+// isSameWidthPlatformConversion returns true when both the source
+// and destination are platform-word-sized integer types (e.g.
+// uintptr -> int). These conversions never truncate bits because
+// Go guarantees both types have the same width on every platform.
+func isSameWidthPlatformConversion(src, dst types.Type) bool {
+ srcBasic, _ := src.Underlying().(*types.Basic)
+ dstBasic, _ := dst.Underlying().(*types.Basic)
+ if srcBasic == nil || dstBasic == nil {
+ return false
+ }
+ return isPlatformWordType(srcBasic.Kind()) &&
+ isPlatformWordType(dstBasic.Kind())
+}
+
+func isPlatformWordType(k types.BasicKind) bool {
+ switch k {
+ case types.Int, types.Uint, types.Uintptr:
+ return true
+ }
+ return false
+}
+
// hasRangeCheck determines if there is a valid range check for the given value that ensures safety.
func (s *overflowState) hasRangeCheck(v ssa.Value, dstInt IntTypeInfo, block *ssa.BasicBlock) bool {
// Clear visited map for new resolution
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/dependency_checker.go b/vendor/github.com/securego/gosec/v2/analyzers/dependency_checker.go
new file mode 100644
index 00000000..2f800ab2
--- /dev/null
+++ b/vendor/github.com/securego/gosec/v2/analyzers/dependency_checker.go
@@ -0,0 +1,116 @@
+// (c) Copyright gosec's authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package analyzers
+
+import "golang.org/x/tools/go/ssa"
+
+type dependencyKey struct {
+ value ssa.Value
+ target ssa.Value
+}
+
+type dependencyChecker struct {
+ memo map[dependencyKey]bool
+ visiting map[dependencyKey]struct{}
+}
+
+func newDependencyChecker() *dependencyChecker {
+ return &dependencyChecker{
+ memo: make(map[dependencyKey]bool),
+ visiting: make(map[dependencyKey]struct{}),
+ }
+}
+
+func (c *dependencyChecker) dependsOn(value ssa.Value, target ssa.Value) bool {
+ return c.dependsOnDepth(value, target, 0)
+}
+
+func (c *dependencyChecker) dependsOnDepth(value ssa.Value, target ssa.Value, depth int) bool {
+ if value == nil || target == nil || depth > MaxDepth {
+ return false
+ }
+ if value == target {
+ return true
+ }
+
+ key := dependencyKey{value: value, target: target}
+ if result, ok := c.memo[key]; ok {
+ return result
+ }
+ if _, ok := c.visiting[key]; ok {
+ return false
+ }
+
+ c.visiting[key] = struct{}{}
+ result := false
+
+ switch v := value.(type) {
+ case *ssa.ChangeType:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.MakeInterface:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.TypeAssert:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.UnOp:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.FieldAddr:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.Field:
+ result = c.dependsOnDepth(v.X, target, depth+1)
+ case *ssa.IndexAddr:
+ result = c.dependsOnDepth(v.X, target, depth+1) || c.dependsOnDepth(v.Index, target, depth+1)
+ case *ssa.Index:
+ result = c.dependsOnDepth(v.X, target, depth+1) || c.dependsOnDepth(v.Index, target, depth+1)
+ case *ssa.Slice:
+ if c.dependsOnDepth(v.X, target, depth+1) {
+ result = true
+ break
+ }
+ if v.Low != nil && c.dependsOnDepth(v.Low, target, depth+1) {
+ result = true
+ break
+ }
+ if v.High != nil && c.dependsOnDepth(v.High, target, depth+1) {
+ result = true
+ break
+ }
+ result = v.Max != nil && c.dependsOnDepth(v.Max, target, depth+1)
+ case *ssa.Extract:
+ result = c.dependsOnDepth(v.Tuple, target, depth+1)
+ case *ssa.Phi:
+ for _, edge := range v.Edges {
+ if c.dependsOnDepth(edge, target, depth+1) {
+ result = true
+ break
+ }
+ }
+ case *ssa.Call:
+ if v.Call.Value != nil && c.dependsOnDepth(v.Call.Value, target, depth+1) {
+ result = true
+ break
+ }
+ for _, arg := range v.Call.Args {
+ if c.dependsOnDepth(arg, target, depth+1) {
+ result = true
+ break
+ }
+ }
+ }
+
+ delete(c.visiting, key)
+ c.memo[key] = result
+
+ return result
+}
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/form_parsing_limits.go b/vendor/github.com/securego/gosec/v2/analyzers/form_parsing_limits.go
index 0c4723f0..8b27d6d1 100644
--- a/vendor/github.com/securego/gosec/v2/analyzers/form_parsing_limits.go
+++ b/vendor/github.com/securego/gosec/v2/analyzers/form_parsing_limits.go
@@ -15,507 +15,38 @@
package analyzers
import (
- "go/token"
- "go/types"
-
"golang.org/x/tools/go/analysis"
- "golang.org/x/tools/go/analysis/passes/buildssa"
- "golang.org/x/tools/go/ssa"
- "github.com/securego/gosec/v2/internal/ssautil"
- "github.com/securego/gosec/v2/issue"
+ "github.com/securego/gosec/v2/taint"
)
-const msgUnboundedFormParsing = "Parsing form data without limiting request body size can allow memory exhaustion (use http.MaxBytesReader)"
-
-type dependencyKey struct {
- value ssa.Value
- target ssa.Value
-}
-
-type dependencyChecker struct {
- memo map[dependencyKey]bool
- visiting map[dependencyKey]struct{}
-}
-
-func newDependencyChecker() *dependencyChecker {
- return &dependencyChecker{
- memo: make(map[dependencyKey]bool),
- visiting: make(map[dependencyKey]struct{}),
- }
-}
-
-func (c *dependencyChecker) dependsOn(value ssa.Value, target ssa.Value) bool {
- return c.dependsOnDepth(value, target, 0)
-}
-
-func (c *dependencyChecker) dependsOnDepth(value ssa.Value, target ssa.Value, depth int) bool {
- if value == nil || target == nil || depth > MaxDepth {
- return false
- }
- if value == target {
- return true
- }
-
- key := dependencyKey{value: value, target: target}
- if result, ok := c.memo[key]; ok {
- return result
- }
- if _, ok := c.visiting[key]; ok {
- return false
- }
-
- c.visiting[key] = struct{}{}
- result := false
-
- switch v := value.(type) {
- case *ssa.ChangeType:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.MakeInterface:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.TypeAssert:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.UnOp:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.FieldAddr:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.Field:
- result = c.dependsOnDepth(v.X, target, depth+1)
- case *ssa.IndexAddr:
- result = c.dependsOnDepth(v.X, target, depth+1) || c.dependsOnDepth(v.Index, target, depth+1)
- case *ssa.Index:
- result = c.dependsOnDepth(v.X, target, depth+1) || c.dependsOnDepth(v.Index, target, depth+1)
- case *ssa.Slice:
- if c.dependsOnDepth(v.X, target, depth+1) {
- result = true
- break
- }
- if v.Low != nil && c.dependsOnDepth(v.Low, target, depth+1) {
- result = true
- break
- }
- if v.High != nil && c.dependsOnDepth(v.High, target, depth+1) {
- result = true
- break
- }
- result = v.Max != nil && c.dependsOnDepth(v.Max, target, depth+1)
- case *ssa.Extract:
- result = c.dependsOnDepth(v.Tuple, target, depth+1)
- case *ssa.Phi:
- for _, edge := range v.Edges {
- if c.dependsOnDepth(edge, target, depth+1) {
- result = true
- break
- }
- }
- case *ssa.Call:
- if v.Call.Value != nil && c.dependsOnDepth(v.Call.Value, target, depth+1) {
- result = true
- break
- }
- for _, arg := range v.Call.Args {
- if c.dependsOnDepth(arg, target, depth+1) {
- result = true
- break
- }
- }
+// FormParsingLimits returns a taint analysis configuration for detecting
+// unbounded multipart form parsing in HTTP handlers.
+//
+// Only ParseMultipartForm is flagged because ParseForm, FormValue, and
+// PostFormValue already enforce a built-in 10 MiB body limit in Go's
+// standard library (see net/http.Request.ParseForm documentation).
+func FormParsingLimits() taint.Config {
+ return taint.Config{
+ Sources: []taint.Source{
+ {Package: "net/http", Name: "Request", Pointer: true},
+ },
+ Sinks: []taint.Sink{
+ // ParseMultipartForm reads the entire body into memory/disk with
+ // no automatic cap — the caller-supplied maxMemory only limits the
+ // in-memory portion while the total can be maxMemory + 10 MiB.
+ // Without http.MaxBytesReader the full body is consumed.
+ // CheckArgs: [0] checks only the receiver (*http.Request).
+ {Package: "net/http", Receiver: "Request", Method: "ParseMultipartForm", Pointer: true, CheckArgs: []int{0}},
+ },
+ Sanitizers: []taint.Sanitizer{},
}
-
- delete(c.visiting, key)
- c.memo[key] = result
-
- return result
}
func newFormParsingLimitAnalyzer(id string, description string) *analysis.Analyzer {
- return &analysis.Analyzer{
- Name: id,
- Doc: description,
- Run: runFormParsingLimitAnalysis,
- Requires: []*analysis.Analyzer{buildssa.Analyzer},
- }
-}
-
-func runFormParsingLimitAnalysis(pass *analysis.Pass) (any, error) {
- ssaResult, err := ssautil.GetSSAResult(pass)
- if err != nil {
- return nil, err
- }
-
- checker := newDependencyChecker()
- issuesByPos := make(map[token.Pos]*issue.Issue)
- handlerProtection := computeFormParsingHandlerProtection(ssaResult.SSA.SrcFuncs, checker)
-
- for _, fn := range collectAnalyzerFunctions(ssaResult.SSA.SrcFuncs) {
- requestParam, writerParam := findHandlerRequestAndWriterParams(fn)
- if requestParam == nil || writerParam == nil {
- continue
- }
-
- hasRequestBodyLimit := handlerProtection[fn]
- if hasRequestBodyLimit {
- continue
- }
-
- for _, block := range fn.Blocks {
- for _, instr := range block.Instrs {
- callInstr, ok := instr.(ssa.CallInstruction)
- if !ok {
- continue
- }
- if !isRiskyFormParsingCall(callInstr, requestParam, checker) {
- continue
- }
- addRedirectIssue(issuesByPos, pass, instr.Pos(), msgUnboundedFormParsing, issue.Medium, issue.High)
- }
- }
- }
-
- if len(issuesByPos) == 0 {
- return nil, nil
- }
-
- issues := make([]*issue.Issue, 0, len(issuesByPos))
- for _, i := range issuesByPos {
- issues = append(issues, i)
- }
-
- return issues, nil
-}
-
-func computeFormParsingHandlerProtection(srcFuncs []*ssa.Function, checker *dependencyChecker) map[*ssa.Function]bool {
- protection := make(map[*ssa.Function]bool)
- allFuncs := collectAnalyzerFunctions(srcFuncs)
- for _, fn := range allFuncs {
- requestParam, writerParam := findHandlerRequestAndWriterParams(fn)
- if requestParam == nil || writerParam == nil {
- continue
- }
- if functionHasRequestBodyLimit(fn, requestParam, writerParam, checker) {
- protection[fn] = true
- continue
- }
- if isProtectedByWrapperCall(fn, allFuncs, checker) {
- protection[fn] = true
- }
- }
-
- return protection
-}
-
-func isProtectedByWrapperCall(handler *ssa.Function, allFuncs []*ssa.Function, checker *dependencyChecker) bool {
- for _, fn := range allFuncs {
- if fn == nil {
- continue
- }
- for _, block := range fn.Blocks {
- for _, instr := range block.Instrs {
- callInstr, ok := instr.(ssa.CallInstruction)
- if !ok {
- continue
- }
- common := callInstr.Common()
- if common == nil {
- continue
- }
- wrapper := common.StaticCallee()
- if wrapper == nil {
- continue
- }
-
- for argIndex, arg := range common.Args {
- if !checker.dependsOn(arg, handler) {
- continue
- }
- if wrapperProtectsParamHandler(wrapper, argIndex, checker) {
- return true
- }
- }
- }
- }
- }
-
- return false
-}
-
-func wrapperProtectsParamHandler(wrapper *ssa.Function, paramIndex int, checker *dependencyChecker) bool {
- if wrapper == nil || paramIndex < 0 || paramIndex >= len(wrapper.Params) {
- return false
- }
- handlerParam := wrapper.Params[paramIndex]
-
- if wrapperDelegatesWithRequestLimit(wrapper, handlerParam, checker) {
- return true
- }
-
- for _, block := range wrapper.Blocks {
- for _, instr := range block.Instrs {
- makeClosure, ok := instr.(*ssa.MakeClosure)
- if !ok {
- continue
- }
- closureFn, ok := makeClosure.Fn.(*ssa.Function)
- if !ok || closureFn == nil {
- continue
- }
-
- requestParam, writerParam := findHandlerRequestAndWriterParams(closureFn)
- if requestParam == nil || writerParam == nil {
- continue
- }
- if !functionHasRequestBodyLimit(closureFn, requestParam, writerParam, checker) {
- continue
- }
-
- for bindingIndex, binding := range makeClosure.Bindings {
- if !bindingDependsOnValue(binding, handlerParam, checker) {
- continue
- }
- if closureDelegatesWithRequestLimit(closureFn, bindingIndex, requestParam, writerParam, checker) {
- return true
- }
- }
- }
- }
-
- return false
-}
-
-func bindingDependsOnValue(binding ssa.Value, target ssa.Value, checker *dependencyChecker) bool {
- if checker.dependsOn(binding, target) {
- return true
- }
-
- alloc, ok := binding.(*ssa.Alloc)
- if !ok {
- return false
- }
-
- for _, ref := range safeReferrers(alloc) {
- store, ok := ref.(*ssa.Store)
- if !ok {
- continue
- }
- if store.Addr != alloc {
- continue
- }
- if checker.dependsOn(store.Val, target) {
- return true
- }
- }
-
- return false
-}
-
-func wrapperDelegatesWithRequestLimit(wrapper *ssa.Function, handlerValue ssa.Value, checker *dependencyChecker) bool {
- requestParam, writerParam := findHandlerRequestAndWriterParams(wrapper)
- if requestParam == nil || writerParam == nil {
- return false
- }
- if !functionHasRequestBodyLimit(wrapper, requestParam, writerParam, checker) {
- return false
- }
- return hasServeHTTPDelegation(wrapper, handlerValue, writerParam, requestParam, checker)
-}
-
-func closureDelegatesWithRequestLimit(closure *ssa.Function, freeVarIndex int, requestParam *ssa.Parameter, writerParam *ssa.Parameter, checker *dependencyChecker) bool {
- if freeVarIndex < 0 || freeVarIndex >= len(closure.FreeVars) {
- return false
- }
- handlerValue := closure.FreeVars[freeVarIndex]
- return hasServeHTTPDelegation(closure, handlerValue, writerParam, requestParam, checker)
-}
-
-func hasServeHTTPDelegation(fn *ssa.Function, handlerValue ssa.Value, writerValue ssa.Value, requestValue ssa.Value, checker *dependencyChecker) bool {
- for _, block := range fn.Blocks {
- for _, instr := range block.Instrs {
- call, ok := instr.(*ssa.Call)
- if !ok {
- continue
- }
- common := call.Common()
- if common == nil {
- continue
- }
-
- var (
- receiver ssa.Value
- writer ssa.Value
- request ssa.Value
- )
-
- if method := common.Method; method != nil && method.Name() == "ServeHTTP" {
- if len(common.Args) < 2 {
- continue
- }
- receiver = common.Value
- writer = common.Args[0]
- request = common.Args[1]
- } else {
- callee := common.StaticCallee()
- if callee == nil || callee.Name() != "ServeHTTP" || callee.Signature == nil || callee.Signature.Recv() == nil {
- continue
- }
- if len(common.Args) < 3 {
- continue
- }
- receiver = common.Args[0]
- writer = common.Args[1]
- request = common.Args[2]
- }
-
- if !checker.dependsOn(receiver, handlerValue) {
- continue
- }
- if !checker.dependsOn(writer, writerValue) {
- continue
- }
- if !checker.dependsOn(request, requestValue) {
- continue
- }
- return true
- }
- }
-
- return false
-}
-
-func findHandlerRequestAndWriterParams(fn *ssa.Function) (*ssa.Parameter, *ssa.Parameter) {
- if fn == nil {
- return nil, nil
- }
-
- var requestParam *ssa.Parameter
- var writerParam *ssa.Parameter
-
- for _, param := range fn.Params {
- if param == nil {
- continue
- }
- if requestParam == nil && isHTTPRequestPointerType(param.Type()) {
- requestParam = param
- continue
- }
- if writerParam == nil && isHTTPResponseWriterType(param.Type()) {
- writerParam = param
- }
- }
-
- return requestParam, writerParam
-}
-
-func isHTTPResponseWriterType(t types.Type) bool {
- named, ok := t.(*types.Named)
- if !ok {
- return false
- }
-
- obj := named.Obj()
- if obj == nil || obj.Name() != "ResponseWriter" {
- return false
- }
-
- pkg := obj.Pkg()
- return pkg != nil && pkg.Path() == "net/http"
-}
-
-func functionHasRequestBodyLimit(fn *ssa.Function, requestParam *ssa.Parameter, writerParam *ssa.Parameter, checker *dependencyChecker) bool {
- for _, block := range fn.Blocks {
- for _, instr := range block.Instrs {
- store, ok := instr.(*ssa.Store)
- if !ok {
- continue
- }
- if isRequestBodyStoreFromMaxBytesReader(store, requestParam, writerParam, checker) {
- return true
- }
- }
- }
- return false
-}
-
-func isRequestBodyStoreFromMaxBytesReader(store *ssa.Store, requestParam *ssa.Parameter, writerParam *ssa.Parameter, checker *dependencyChecker) bool {
- fieldAddr, ok := store.Addr.(*ssa.FieldAddr)
- if !ok {
- return false
- }
-
- if !checker.dependsOn(fieldAddr.X, requestParam) {
- return false
- }
-
- if !isMaxBytesReaderValue(store.Val, requestParam, writerParam, checker, 0) {
- return false
- }
-
- return true
-}
-
-func isMaxBytesReaderValue(v ssa.Value, requestParam *ssa.Parameter, writerParam *ssa.Parameter, checker *dependencyChecker, depth int) bool {
- if v == nil || depth > MaxDepth {
- return false
- }
-
- switch value := v.(type) {
- case *ssa.Call:
- callee := value.Call.StaticCallee()
- if callee == nil || callee.Name() != "MaxBytesReader" {
- return false
- }
- if callee.Pkg == nil || callee.Pkg.Pkg == nil || callee.Pkg.Pkg.Path() != "net/http" {
- return false
- }
- if len(value.Call.Args) < 3 {
- return false
- }
- if !checker.dependsOn(value.Call.Args[0], writerParam) {
- return false
- }
- return checker.dependsOn(value.Call.Args[1], requestParam)
- case *ssa.ChangeType:
- return isMaxBytesReaderValue(value.X, requestParam, writerParam, checker, depth+1)
- case *ssa.MakeInterface:
- return isMaxBytesReaderValue(value.X, requestParam, writerParam, checker, depth+1)
- case *ssa.TypeAssert:
- return isMaxBytesReaderValue(value.X, requestParam, writerParam, checker, depth+1)
- case *ssa.Phi:
- for _, edge := range value.Edges {
- if isMaxBytesReaderValue(edge, requestParam, writerParam, checker, depth+1) {
- return true
- }
- }
- }
-
- return false
-}
-
-func isRiskyFormParsingCall(callInstr ssa.CallInstruction, requestParam *ssa.Parameter, checker *dependencyChecker) bool {
- common := callInstr.Common()
- if common == nil {
- return false
- }
-
- callee := common.StaticCallee()
- if callee == nil {
- return false
- }
-
- if callee.Signature == nil || callee.Signature.Recv() == nil {
- return false
- }
-
- if !isHTTPRequestPointerType(callee.Signature.Recv().Type()) {
- return false
- }
-
- name := callee.Name()
- if name != "ParseForm" && name != "ParseMultipartForm" && name != "FormValue" && name != "PostFormValue" {
- return false
- }
-
- if len(common.Args) == 0 {
- return false
- }
-
- return checker.dependsOn(common.Args[0], requestParam)
+ config := FormParsingLimits()
+ rule := FormParsingLimitRule
+ rule.ID = id
+ rule.Description = description
+ return taint.NewGosecAnalyzer(&rule, &config)
}
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/insecure_cookie.go b/vendor/github.com/securego/gosec/v2/analyzers/insecure_cookie.go
new file mode 100644
index 00000000..5c22eeb6
--- /dev/null
+++ b/vendor/github.com/securego/gosec/v2/analyzers/insecure_cookie.go
@@ -0,0 +1,269 @@
+// (c) Copyright gosec's authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package analyzers
+
+import (
+ "go/constant"
+ "go/token"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/buildssa"
+ "golang.org/x/tools/go/ssa"
+
+ "github.com/securego/gosec/v2/internal/ssautil"
+ "github.com/securego/gosec/v2/issue"
+)
+
+func newInsecureCookieAnalyzer(id string, description string) *analysis.Analyzer {
+ return &analysis.Analyzer{
+ Name: id,
+ Doc: description,
+ Run: runInsecureCookieAnalysis,
+ Requires: []*analysis.Analyzer{buildssa.Analyzer},
+ }
+}
+
+// cookieState tracks the security-relevant fields set on a single http.Cookie allocation.
+type cookieState struct {
+ allocPos token.Pos
+ secureSet bool
+ httpOnlySet bool
+ sameSiteSet bool
+ // Track the actual values when explicitly set
+ secureTrue bool
+ httpOnlyTrue bool
+ sameSiteSafe bool // SameSiteStrictMode (3) or SameSiteLaxMode (2)
+}
+
+type insecureCookieState struct {
+ *BaseAnalyzerState
+ cookies map[ssa.Value]*cookieState
+ issuesByPos map[token.Pos]*issue.Issue
+}
+
+func newInsecureCookieState(pass *analysis.Pass) *insecureCookieState {
+ return &insecureCookieState{
+ BaseAnalyzerState: NewBaseState(pass),
+ cookies: make(map[ssa.Value]*cookieState),
+ issuesByPos: make(map[token.Pos]*issue.Issue),
+ }
+}
+
+func runInsecureCookieAnalysis(pass *analysis.Pass) (any, error) {
+ ssaResult, err := ssautil.GetSSAResult(pass)
+ if err != nil {
+ return nil, err
+ }
+
+ state := newInsecureCookieState(pass)
+ defer state.Release()
+
+ funcs := collectAnalyzerFunctions(ssaResult.SSA.SrcFuncs)
+ if len(funcs) == 0 {
+ return nil, nil
+ }
+
+ // Phase 1: Collect field stores on http.Cookie allocations.
+ TraverseSSA(funcs, func(_ *ssa.BasicBlock, instr ssa.Instruction) {
+ store, ok := instr.(*ssa.Store)
+ if !ok {
+ return
+ }
+ state.trackCookieFieldStore(store)
+ })
+
+ // Phase 2: Report cookies missing secure attributes.
+ state.reportInsecureCookies()
+
+ if len(state.issuesByPos) == 0 {
+ return nil, nil
+ }
+
+ issues := make([]*issue.Issue, 0, len(state.issuesByPos))
+ for _, i := range state.issuesByPos {
+ issues = append(issues, i)
+ }
+ return issues, nil
+}
+
+func (s *insecureCookieState) trackCookieFieldStore(store *ssa.Store) {
+ fieldAddr, ok := store.Addr.(*ssa.FieldAddr)
+ if !ok {
+ return
+ }
+
+ if !isHTTPCookiePointerType(fieldAddr.X.Type()) {
+ return
+ }
+
+ fieldName, ok := httpCookieFieldName(fieldAddr)
+ if !ok {
+ return
+ }
+
+ root := cookieRoot(fieldAddr.X, 0)
+ if root == nil {
+ return
+ }
+
+ cs := s.getOrCreateCookieState(root)
+
+ switch fieldName {
+ case "Secure":
+ cs.secureSet = true
+ if b, ok := boolConstValue(store.Val); ok {
+ cs.secureTrue = b
+ }
+ case "HttpOnly":
+ cs.httpOnlySet = true
+ if b, ok := boolConstValue(store.Val); ok {
+ cs.httpOnlyTrue = b
+ }
+ case "SameSite":
+ cs.sameSiteSet = true
+ if c, ok := store.Val.(*ssa.Const); ok && c.Value != nil {
+ // http.SameSiteLaxMode = 2, http.SameSiteStrictMode = 3
+ val, isInt := intConstValue(c)
+ if isInt && (val == 2 || val == 3) {
+ cs.sameSiteSafe = true
+ }
+ }
+ }
+}
+
+func (s *insecureCookieState) getOrCreateCookieState(root ssa.Value) *cookieState {
+ if cs, ok := s.cookies[root]; ok {
+ return cs
+ }
+ cs := &cookieState{allocPos: root.Pos()}
+ s.cookies[root] = cs
+ return cs
+}
+
+func (s *insecureCookieState) reportInsecureCookies() {
+ for _, cs := range s.cookies {
+ if cs.allocPos == token.NoPos {
+ continue
+ }
+
+ // Check: Secure must be explicitly set to true
+ if !cs.secureSet || !cs.secureTrue {
+ s.addIssue(cs.allocPos, "http.Cookie missing or has insecure Secure, HttpOnly, or SameSite attribute")
+ continue
+ }
+ // Check: HttpOnly must be explicitly set to true
+ if !cs.httpOnlySet || !cs.httpOnlyTrue {
+ s.addIssue(cs.allocPos, "http.Cookie missing or has insecure Secure, HttpOnly, or SameSite attribute")
+ continue
+ }
+ // Check: SameSite must be Lax or Strict
+ if !cs.sameSiteSet || !cs.sameSiteSafe {
+ s.addIssue(cs.allocPos, "http.Cookie missing or has insecure Secure, HttpOnly, or SameSite attribute")
+ continue
+ }
+ }
+}
+
+func (s *insecureCookieState) addIssue(pos token.Pos, msg string) {
+ if pos == token.NoPos {
+ return
+ }
+ if _, exists := s.issuesByPos[pos]; exists {
+ return
+ }
+ s.issuesByPos[pos] = newIssue(s.Pass.Analyzer.Name, msg, s.Pass.Fset, pos, issue.Medium, issue.High)
+}
+
+// isHTTPCookiePointerType returns true if t is *net/http.Cookie.
+func isHTTPCookiePointerType(t types.Type) bool {
+ ptr, ok := t.(*types.Pointer)
+ if !ok {
+ return false
+ }
+ named, ok := ptr.Elem().(*types.Named)
+ if !ok {
+ return false
+ }
+ obj := named.Obj()
+ if obj == nil || obj.Name() != "Cookie" {
+ return false
+ }
+ pkg := obj.Pkg()
+ return pkg != nil && pkg.Path() == "net/http"
+}
+
+// httpCookieFieldName returns the field name for a FieldAddr on *http.Cookie.
+func httpCookieFieldName(fieldAddr *ssa.FieldAddr) (string, bool) {
+ if fieldAddr == nil {
+ return "", false
+ }
+ t := fieldAddr.X.Type()
+ if ptr, ok := t.(*types.Pointer); ok {
+ t = ptr.Elem()
+ }
+ named, ok := t.(*types.Named)
+ if !ok {
+ return "", false
+ }
+ if named.Obj() == nil || named.Obj().Pkg() == nil ||
+ named.Obj().Pkg().Path() != "net/http" || named.Obj().Name() != "Cookie" {
+ return "", false
+ }
+ st, ok := named.Underlying().(*types.Struct)
+ if !ok || fieldAddr.Field >= st.NumFields() {
+ return "", false
+ }
+ return st.Field(fieldAddr.Field).Name(), true
+}
+
+// cookieRoot traces a value back to its http.Cookie allocation root.
+func cookieRoot(v ssa.Value, depth int) ssa.Value {
+ if v == nil || depth > MaxDepth {
+ return nil
+ }
+ if isHTTPCookiePointerType(v.Type()) {
+ return v
+ }
+ switch value := v.(type) {
+ case *ssa.ChangeType:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.MakeInterface:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.TypeAssert:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.UnOp:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.FieldAddr:
+ return cookieRoot(value.X, depth+1)
+ case *ssa.Phi:
+ if len(value.Edges) > 0 {
+ return cookieRoot(value.Edges[0], depth+1)
+ }
+ }
+ return nil
+}
+
+// intConstValue extracts an int64 from an ssa.Const.
+func intConstValue(c *ssa.Const) (int64, bool) {
+ if c == nil || c.Value == nil {
+ return 0, false
+ }
+ if c.Value.Kind() != constant.Int {
+ return 0, false
+ }
+ val, ok := constant.Int64Val(c.Value)
+ return val, ok
+}
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/loginjection.go b/vendor/github.com/securego/gosec/v2/analyzers/loginjection.go
index 2cbd1135..a6abe2f9 100644
--- a/vendor/github.com/securego/gosec/v2/analyzers/loginjection.go
+++ b/vendor/github.com/securego/gosec/v2/analyzers/loginjection.go
@@ -46,10 +46,19 @@ func LogInjection() taint.Config {
{Package: "log", Method: "Panic"},
{Package: "log", Method: "Panicf"},
{Package: "log", Method: "Panicln"},
- {Package: "log/slog", Method: "Info"},
- {Package: "log/slog", Method: "Warn"},
- {Package: "log/slog", Method: "Error"},
- {Package: "log/slog", Method: "Debug"},
+ // log/slog structured logging functions have the signature:
+ // func Warn(msg string, args ...any)
+ // The variadic `args` are key-value attribute pairs whose values are
+ // automatically escaped by both TextHandler (JSON-quoted) and JSONHandler
+ // (JSON-encoded), making them safe against log injection.
+ // Only the `msg` argument (args[0]) is a real injection vector because
+ // TextHandler writes it verbatim without quoting.
+ // CheckArgs: []int{0} scopes the taint check to the message only,
+ // preventing false positives on: slog.Warn("msg", "key", taintedVal)
+ {Package: "log/slog", Method: "Info", CheckArgs: []int{0}},
+ {Package: "log/slog", Method: "Warn", CheckArgs: []int{0}},
+ {Package: "log/slog", Method: "Error", CheckArgs: []int{0}},
+ {Package: "log/slog", Method: "Debug", CheckArgs: []int{0}},
},
Sanitizers: []taint.Sanitizer{
// strings.ReplaceAll can strip newlines/CRLF for log injection
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/openredirect.go b/vendor/github.com/securego/gosec/v2/analyzers/openredirect.go
new file mode 100644
index 00000000..bcdddc96
--- /dev/null
+++ b/vendor/github.com/securego/gosec/v2/analyzers/openredirect.go
@@ -0,0 +1,67 @@
+// (c) Copyright gosec's authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package analyzers
+
+import (
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/securego/gosec/v2/taint"
+)
+
+// OpenRedirect returns a configuration for detecting open-redirect vulnerabilities
+// where user-controlled data flows into the URL argument of net/http.Redirect.
+// See CWE-601.
+func OpenRedirect() taint.Config {
+ return taint.Config{
+ Sources: []taint.Source{
+ // Type sources: tainted when received as parameters from external callers.
+ // Any read from a *http.Request (FormValue, URL.Query().Get, Cookie, etc.)
+ // propagates taint through the existing receiver-based logic in isTainted.
+ {Package: "net/http", Name: "Request", Pointer: true},
+ {Package: "net/url", Name: "URL", Pointer: true},
+ {Package: "net/url", Name: "Values"},
+ },
+ Sinks: []taint.Sink{
+ // http.Redirect(w, r, url, code): only the URL string (arg index 2)
+ // is the redirect target. Skipping arg 1 (*http.Request) prevents the
+ // receiver itself from being treated as a tainted sink argument.
+ {Package: "net/http", Method: "Redirect", CheckArgs: []int{2}},
+ },
+ Sanitizers: []taint.Sanitizer{
+ // url.PathEscape / QueryEscape neutralize untrusted path or query
+ // fragments embedded into a hard-coded base URL.
+ {Package: "net/url", Method: "PathEscape"},
+ {Package: "net/url", Method: "QueryEscape"},
+
+ // Numeric conversions cannot produce a URL host or scheme.
+ {Package: "strconv", Method: "Atoi"},
+ {Package: "strconv", Method: "Itoa"},
+ {Package: "strconv", Method: "ParseInt"},
+ {Package: "strconv", Method: "ParseUint"},
+ {Package: "strconv", Method: "FormatInt"},
+ {Package: "strconv", Method: "FormatUint"},
+ },
+ }
+}
+
+// newOpenRedirectAnalyzer creates an analyzer for detecting open-redirect
+// vulnerabilities via taint analysis (G710).
+func newOpenRedirectAnalyzer(id string, description string) *analysis.Analyzer {
+ config := OpenRedirect()
+ rule := OpenRedirectRule
+ rule.ID = id
+ rule.Description = description
+ return taint.NewGosecAnalyzer(&rule, &config)
+}
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/pathtraversal.go b/vendor/github.com/securego/gosec/v2/analyzers/pathtraversal.go
index 34142982..ba9b72e8 100644
--- a/vendor/github.com/securego/gosec/v2/analyzers/pathtraversal.go
+++ b/vendor/github.com/securego/gosec/v2/analyzers/pathtraversal.go
@@ -61,10 +61,15 @@ func PathTraversal() taint.Config {
{Package: "io/ioutil", Method: "ReadDir"},
{Package: "path/filepath", Method: "Walk"},
{Package: "path/filepath", Method: "WalkDir"},
+ // HTTP file-serving functions: user-controlled path = arbitrary file read
+ {Package: "net/http", Method: "ServeFile", CheckArgs: []int{2}},
+ {Package: "net/http", Method: "ServeFileFS", CheckArgs: []int{3}},
},
Sanitizers: []taint.Sanitizer{
// filepath.Clean normalizes and removes traversal components
{Package: "path/filepath", Method: "Clean"},
+ // filepath.Abs calls Clean internally (per Go docs)
+ {Package: "path/filepath", Method: "Abs"},
// filepath.Base extracts just the filename, removing directory traversal
{Package: "path/filepath", Method: "Base"},
// filepath.Rel computes a relative path safely
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/range_analyzer.go b/vendor/github.com/securego/gosec/v2/analyzers/range_analyzer.go
index 42a4ad80..962f189b 100644
--- a/vendor/github.com/securego/gosec/v2/analyzers/range_analyzer.go
+++ b/vendor/github.com/securego/gosec/v2/analyzers/range_analyzer.go
@@ -494,6 +494,12 @@ func (ra *RangeAnalyzer) isNonNegativeRecursive(v ssa.Value) bool {
return true
}
+ // Elements loaded from a []rune slice created by converting a
+ // string are valid Unicode code points, guaranteed non-negative.
+ if isElementOfStringRuneSlice(v) {
+ return true
+ }
+
v, info := getRealValueFromOperation(v)
if info.op == "neg" || info.op == "-" {
return false
@@ -565,6 +571,44 @@ func (ra *RangeAnalyzer) isNonNegativeRecursive(v ssa.Value) bool {
return false
}
+// isElementOfStringRuneSlice checks whether v is a value loaded
+// from a []rune slice that was created by converting a string.
+// Go guarantees that string-to-[]rune conversions produce valid
+// Unicode code points (>= 0), so every element is non-negative.
+func isElementOfStringRuneSlice(v ssa.Value) bool {
+ unOp, ok := v.(*ssa.UnOp)
+ if !ok || unOp.Op != token.MUL {
+ return false
+ }
+ idx, ok := unOp.X.(*ssa.IndexAddr)
+ if !ok {
+ return false
+ }
+ return isStringToRuneConversion(idx.X)
+}
+
+// isStringToRuneConversion returns true when v is a Convert from
+// string to []int32 (i.e. []rune).
+func isStringToRuneConversion(v ssa.Value) bool {
+ conv, ok := v.(*ssa.Convert)
+ if !ok {
+ return false
+ }
+ srcBasic, ok := conv.X.Type().Underlying().(*types.Basic)
+ if !ok || srcBasic.Kind() != types.String {
+ return false
+ }
+ dstSlice, ok := conv.Type().Underlying().(*types.Slice)
+ if !ok {
+ return false
+ }
+ elemBasic, ok := dstSlice.Elem().Underlying().(*types.Basic)
+ if !ok {
+ return false
+ }
+ return elemBasic.Kind() == types.Int32
+}
+
func (ra *RangeAnalyzer) ComputeRange(v ssa.Value, block *ssa.BasicBlock) *rangeResult {
res := ra.acquireResult()
isSrcUnsigned := isUint(v)
@@ -965,7 +1009,7 @@ func (ra *RangeAnalyzer) ComputeRange(v ssa.Value, block *ssa.BasicBlock) *range
res.minValue = minBounds(res.minValue, res.minValueSet, argRes.minValue, argRes.minValueSet, isSrcUnsigned)
res.minValueSet = res.minValueSet && argRes.minValueSet
res.maxValue = minBounds(res.maxValue, res.maxValueSet, argRes.maxValue, argRes.maxValueSet, isSrcUnsigned)
- res.maxValueSet = res.maxValueSet && argRes.maxValueSet
+ res.maxValueSet = res.maxValueSet || argRes.maxValueSet
}
ra.releaseResult(argRes)
}
@@ -979,7 +1023,7 @@ func (ra *RangeAnalyzer) ComputeRange(v ssa.Value, block *ssa.BasicBlock) *range
res.CopyFrom(argRes)
} else {
res.minValue = maxBounds(res.minValue, res.minValueSet, argRes.minValue, argRes.minValueSet, isSrcUnsigned)
- res.minValueSet = res.minValueSet && argRes.minValueSet
+ res.minValueSet = res.minValueSet || argRes.minValueSet
res.maxValue = maxBounds(res.maxValue, res.maxValueSet, argRes.maxValue, argRes.maxValueSet, isSrcUnsigned)
res.maxValueSet = res.maxValueSet && argRes.maxValueSet
}
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/ssti.go b/vendor/github.com/securego/gosec/v2/analyzers/ssti.go
new file mode 100644
index 00000000..f40d74d5
--- /dev/null
+++ b/vendor/github.com/securego/gosec/v2/analyzers/ssti.go
@@ -0,0 +1,104 @@
+// (c) Copyright gosec's authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package analyzers
+
+import (
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/securego/gosec/v2/taint"
+)
+
+// SSTI returns a configuration for detecting Server-Side Template Injection
+// vulnerabilities via text/template.
+//
+// The text/template package performs NO auto-escaping and allows calling any
+// exported method on the data object passed to Execute. When user-controlled
+// input flows into Template.Parse, an attacker can invoke arbitrary methods,
+// read files, or achieve remote code execution depending on available gadgets.
+//
+// Even when the template string is static, rendering user data through
+// text/template into an HTTP response produces unescaped HTML, enabling XSS.
+func SSTI() taint.Config {
+ return taint.Config{
+ Sources: []taint.Source{
+ // Type sources: tainted when received as parameters
+ {Package: "net/http", Name: "Request", Pointer: true},
+ {Package: "net/url", Name: "Values"},
+
+ // Function sources
+ {Package: "os", Name: "Args", IsFunc: true},
+ {Package: "os", Name: "Getenv", IsFunc: true},
+
+ // I/O sources
+ {Package: "bufio", Name: "Reader", Pointer: true},
+ {Package: "bufio", Name: "Scanner", Pointer: true},
+ },
+ Sinks: []taint.Sink{
+ // CRITICAL: user input flows into the template string itself.
+ // Template.Parse takes a single string argument (the template text).
+ {Package: "text/template", Receiver: "Template", Method: "Parse", Pointer: true, CheckArgs: []int{1}},
+
+ // text/template.Must wraps Parse; arg[0] is the (*Template, error) pair
+ // but in practice the taint flows through the Parse call above.
+
+ // HIGH: text/template.Execute writes unescaped output to an HTTP response.
+ // Guard: only flag when the writer (arg 1) implements net/http.ResponseWriter.
+ {
+ Package: "text/template",
+ Receiver: "Template",
+ Method: "Execute",
+ Pointer: true,
+ CheckArgs: []int{2},
+ ArgTypeGuards: map[int]string{1: "net/http.ResponseWriter"},
+ },
+ {
+ Package: "text/template",
+ Receiver: "Template",
+ Method: "ExecuteTemplate",
+ Pointer: true,
+ CheckArgs: []int{3},
+ ArgTypeGuards: map[int]string{1: "net/http.ResponseWriter"},
+ },
+ },
+ Sanitizers: []taint.Sanitizer{
+ // HTML escaping neutralizes both SSTI template directives and XSS payloads
+ {Package: "html", Method: "EscapeString"},
+ {Package: "html/template", Method: "HTMLEscapeString"},
+ {Package: "html/template", Method: "JSEscapeString"},
+ {Package: "net/url", Method: "QueryEscape"},
+ {Package: "net/url", Method: "PathEscape"},
+
+ // Numeric conversions produce safe output
+ {Package: "strconv", Method: "Atoi"},
+ {Package: "strconv", Method: "Itoa"},
+ {Package: "strconv", Method: "ParseInt"},
+ {Package: "strconv", Method: "ParseUint"},
+ {Package: "strconv", Method: "ParseFloat"},
+ {Package: "strconv", Method: "FormatInt"},
+ {Package: "strconv", Method: "FormatUint"},
+ {Package: "strconv", Method: "FormatFloat"},
+ },
+ }
+}
+
+// newSSTIAnalyzer creates an analyzer for detecting Server-Side Template
+// Injection vulnerabilities via taint analysis (G708).
+func newSSTIAnalyzer(id string, description string) *analysis.Analyzer {
+ config := SSTI()
+ rule := SSTIRule
+ rule.ID = id
+ rule.Description = description
+ return taint.NewGosecAnalyzer(&rule, &config)
+}
diff --git a/vendor/github.com/securego/gosec/v2/analyzers/unsafe_deserialization.go b/vendor/github.com/securego/gosec/v2/analyzers/unsafe_deserialization.go
new file mode 100644
index 00000000..bbdac51e
--- /dev/null
+++ b/vendor/github.com/securego/gosec/v2/analyzers/unsafe_deserialization.go
@@ -0,0 +1,87 @@
+// (c) Copyright gosec's authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package analyzers
+
+import (
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/securego/gosec/v2/taint"
+)
+
+// UnsafeDeserialization returns a configuration for detecting unsafe
+// deserialization of untrusted data.
+//
+// Go's encoding/gob package embeds full type information in its wire format
+// and will instantiate arbitrary registered types during decode. When an HTTP
+// handler passes r.Body directly to gob.NewDecoder().Decode(), an attacker
+// controls which types get instantiated, leading to denial-of-service or
+// potential RCE (CVE-2024-34156).
+//
+// gopkg.in/yaml.v2's Unmarshal into interface{} can instantiate arbitrary Go
+// types via YAML tags. encoding/xml is susceptible to deeply-nested structure
+// DoS and external entity expansion.
+func UnsafeDeserialization() taint.Config {
+ return taint.Config{
+ Sources: []taint.Source{
+ // Type sources: tainted when received as parameters
+ {Package: "net/http", Name: "Request", Pointer: true},
+ {Package: "net/url", Name: "Values"},
+
+ // Function sources
+ {Package: "os", Name: "Args", IsFunc: true},
+ {Package: "os", Name: "Getenv", IsFunc: true},
+
+ // I/O sources
+ {Package: "bufio", Name: "Reader", Pointer: true},
+ {Package: "bufio", Name: "Scanner", Pointer: true},
+ },
+ Sinks: []taint.Sink{
+ // encoding/gob — highest risk: arbitrary type instantiation from wire format
+ // gob.NewDecoder takes an io.Reader (arg 0), so if the reader is tainted
+ // the decoder will process attacker-controlled data.
+ {Package: "encoding/gob", Method: "NewDecoder", CheckArgs: []int{0}},
+
+ // gopkg.in/yaml.v2 — Unmarshal([]byte, interface{}) can instantiate arbitrary types
+ {Package: "gopkg.in/yaml.v2", Method: "Unmarshal", CheckArgs: []int{0}},
+ // yaml.NewDecoder takes an io.Reader (arg 0)
+ {Package: "gopkg.in/yaml.v2", Method: "NewDecoder", CheckArgs: []int{0}},
+
+ // encoding/xml — deeply-nested structure DoS, entity expansion
+ {Package: "encoding/xml", Method: "NewDecoder", CheckArgs: []int{0}},
+ {Package: "encoding/xml", Method: "Unmarshal", CheckArgs: []int{0}},
+ },
+ Sanitizers: []taint.Sanitizer{
+ // io.LimitReader bounds the amount of data read, mitigating DoS amplification
+ {Package: "io", Method: "LimitReader"},
+
+ // Numeric conversions — result is safe
+ {Package: "strconv", Method: "Atoi"},
+ {Package: "strconv", Method: "Itoa"},
+ {Package: "strconv", Method: "ParseInt"},
+ {Package: "strconv", Method: "ParseUint"},
+ {Package: "strconv", Method: "ParseFloat"},
+ },
+ }
+}
+
+// newUnsafeDeserializationAnalyzer creates an analyzer for detecting unsafe
+// deserialization of untrusted data via taint analysis (G709).
+func newUnsafeDeserializationAnalyzer(id string, description string) *analysis.Analyzer {
+ config := UnsafeDeserialization()
+ rule := UnsafeDeserializationRule
+ rule.ID = id
+ rule.Description = description
+ return taint.NewGosecAnalyzer(&rule, &config)
+}
diff --git a/vendor/github.com/securego/gosec/v2/config.go b/vendor/github.com/securego/gosec/v2/config.go
index 69b8f13e..954daaba 100644
--- a/vendor/github.com/securego/gosec/v2/config.go
+++ b/vendor/github.com/securego/gosec/v2/config.go
@@ -33,6 +33,15 @@ const (
IncludeRules GlobalOption = "include"
// SSA global option to enable go analysis framework with SSA support
SSA GlobalOption = "ssa"
+ // NoSecRequireRules global option requires at least one rule ID in every
+ // #nosec / //gosec:disable annotation. When enabled, naked directives no
+ // longer suppress any findings and an error is reported instead.
+ NoSecRequireRules GlobalOption = "nosec-require-rules"
+ // NoSecRequireJustification global option requires a `-- justification`
+ // in every #nosec / //gosec:disable annotation. When enabled, directives
+ // without a justification no longer suppress any findings and an error is
+ // reported instead.
+ NoSecRequireJustification GlobalOption = "nosec-require-justification"
)
// NoSecTag returns the tag used to disable gosec for a line of code.
diff --git a/vendor/github.com/securego/gosec/v2/cwe/data.go b/vendor/github.com/securego/gosec/v2/cwe/data.go
index c8bfc27d..16f7645c 100644
--- a/vendor/github.com/securego/gosec/v2/cwe/data.go
+++ b/vendor/github.com/securego/gosec/v2/cwe/data.go
@@ -48,6 +48,11 @@ var idWeaknesses = map[string]*Weakness{
Description: "The software does not properly neutralize CRLF sequences before using externally-influenced input in protocol elements that rely on CRLF as delimiters, allowing attackers to inject additional commands or headers.",
Name: "Improper Neutralization of CRLF Sequences ('CRLF Injection')",
},
+ "94": {
+ ID: "94",
+ Description: "The software constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.",
+ Name: "Improper Control of Generation of Code ('Code Injection')",
+ },
"118": {
ID: "118",
Description: "The software does not restrict or incorrectly restricts operations within the boundaries of a resource that is accessed using an index or pointer, such as memory or files.",
@@ -163,6 +168,26 @@ var idWeaknesses = map[string]*Weakness{
Description: "The product uses a cryptographic primitive that uses an Initialization Vector (IV), but the product does not generate IVs that are sufficiently unpredictable or unique according to the expected cryptographic requirements for that primitive.",
Name: "Generation of Weak Initialization Vector (IV)",
},
+ "117": {
+ ID: "117",
+ Description: "The software does not neutralize or incorrectly neutralizes output that is written to logs.",
+ Name: "Improper Output Neutralization for Logs",
+ },
+ "502": {
+ ID: "502",
+ Description: "The application deserializes untrusted data without sufficiently verifying that the resulting data will be valid.",
+ Name: "Deserialization of Untrusted Data",
+ },
+ "614": {
+ ID: "614",
+ Description: "The Secure attribute for a sensitive cookie is not set, which could cause the user agent to send that cookie in plaintext over an HTTP session.",
+ Name: "Sensitive Cookie in HTTPS Session Without 'Secure' Attribute",
+ },
+ "918": {
+ ID: "918",
+ Description: "The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.",
+ Name: "Server-Side Request Forgery (SSRF)",
+ },
}
// Get Retrieves a CWE weakness by it's id
diff --git a/vendor/github.com/securego/gosec/v2/issue/issue.go b/vendor/github.com/securego/gosec/v2/issue/issue.go
index c0d485f7..f2cc986d 100644
--- a/vendor/github.com/securego/gosec/v2/issue/issue.go
+++ b/vendor/github.com/securego/gosec/v2/issue/issue.go
@@ -52,7 +52,9 @@ func GetCweByRule(id string) *cwe.Weakness {
return nil
}
-// ruleToCWE maps gosec rules to CWEs
+// ruleToCWE maps gosec rules to CWEs. The key is the rule ID
+// and the value is the CWE ID. If a rule does not have a CWE,
+// it will not be included in this map.
var ruleToCWE = map[string]string{
"G101": "798",
"G102": "200",
@@ -65,7 +67,10 @@ var ruleToCWE = map[string]string{
"G110": "409",
"G111": "22",
"G112": "400",
+ "G113": "444",
"G707": "93",
+ "G708": "94",
+ "G709": "502",
"G114": "676",
"G115": "190",
"G116": "838",
@@ -76,6 +81,7 @@ var ruleToCWE = map[string]string{
"G121": "346",
"G122": "367",
"G123": "295",
+ "G124": "614",
"G201": "89",
"G202": "89",
"G203": "79",
@@ -86,6 +92,7 @@ var ruleToCWE = map[string]string{
"G304": "22",
"G305": "22",
"G306": "276",
+ "G307": "276",
"G401": "328",
"G402": "295",
"G403": "310",
@@ -103,6 +110,13 @@ var ruleToCWE = map[string]string{
"G507": "327",
"G601": "118",
"G602": "118",
+ "G701": "89",
+ "G702": "78",
+ "G703": "22",
+ "G704": "918",
+ "G705": "79",
+ "G706": "117",
+ "G710": "601",
}
// Issue is returned by a gosec rule if it discovers an issue with the scanned code.
diff --git a/vendor/github.com/securego/gosec/v2/renovate.json b/vendor/github.com/securego/gosec/v2/renovate.json
index 58ee1e0e..9f03abc0 100644
--- a/vendor/github.com/securego/gosec/v2/renovate.json
+++ b/vendor/github.com/securego/gosec/v2/renovate.json
@@ -1,25 +1,52 @@
{
- "dependencyDashboard": true,
- "dependencyDashboardTitle" : "Renovate(bot) : dependency dashboard",
- "vulnerabilityAlerts": {
- "enabled": true
- },
- "extends": [
- ":preserveSemverRanges",
- "group:all",
- "schedule:weekly"
- ],
- "lockFileMaintenance": {
- "commitMessageAction": "Update",
- "enabled": true,
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "dependencyDashboard": true,
+ "dependencyDashboardTitle": "Renovate(bot) : dependency dashboard",
+ "vulnerabilityAlerts": {
+ "enabled": true
+ },
"extends": [
- "group:all",
- "schedule:weekly"
- ]
- },
- "postUpdateOptions": [
- "gomodTidy",
- "gomodUpdateImportPaths"
- ],
- "separateMajorMinor": false
+ "config:best-practices",
+ "helpers:pinGitHubActionDigests",
+ "schedule:weekly"
+ ],
+ "recreateWhen": "always",
+ "packageRules": [
+ {
+ "matchPackageNames": ["*"],
+ "groupName": "all dependencies",
+ "groupSlug": "all"
+ },
+ {
+ "description": "Run pin updates immediately, outside of weekly schedule",
+ "matchUpdateTypes": ["pin"],
+ "schedule": ["at any time"]
+ },
+ {
+ "description": "Skip digest pinning for bare branch refs - these cannot be pinned reliably",
+ "matchPackageNames": ["ccojocar/barry", "securego/gosec"],
+ "matchManagers": ["github-actions"],
+ "pinDigests": false
+ },
+ {
+ "description": "Enable vulnerability alerts for indirect Go dependencies",
+ "matchDepTypes": ["indirect"],
+ "matchManagers": ["gomod"],
+ "enabled": true,
+ "vulnerabilityAlerts": {
+ "enabled": true
+ }
+ }
+ ],
+ "lockFileMaintenance": {
+ "commitMessageAction": "Update",
+ "enabled": true,
+ "schedule": ["before 3am on monday"],
+ "branchPrefix": "renovate/"
+ },
+ "postUpdateOptions": [
+ "gomodTidy",
+ "gomodUpdateImportPaths"
+ ],
+ "separateMajorMinor": false
}
diff --git a/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go b/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go
index b0d5fdad..c0639a3d 100644
--- a/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go
+++ b/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go
@@ -63,6 +63,10 @@ var secretsPatterns = [...]secretPattern{
name: "AWS API Key",
regexp: regexp.MustCompile(`AKIA[0-9A-Z]{16}`),
},
+ {
+ name: "AWS Temporary Access Key",
+ regexp: regexp.MustCompile(`ASIA[0-9A-Z]{16}`),
+ },
{
name: "Amazon MWS Auth Token",
regexp: regexp.MustCompile(`amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`),
@@ -163,6 +167,19 @@ var secretsPatterns = [...]secretPattern{
name: "Twitter OAuth",
regexp: regexp.MustCompile(`[tT][wW][iI][tT][tT][eE][rR].*[''|"][0-9a-zA-Z]{35,44}[''|"]`),
},
+
+ {
+ name: "GitHub personal access token",
+ regexp: regexp.MustCompile(`ghp_[a-zA-Z0-9]{36}`),
+ },
+ {
+ name: "GitHub fine-grained access token",
+ regexp: regexp.MustCompile(`github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}`),
+ },
+ {
+ name: "GitHub action temporary token",
+ regexp: regexp.MustCompile(`ghs_[a-zA-Z0-9]{36}`),
+ },
}
type credentials struct {
diff --git a/vendor/github.com/securego/gosec/v2/rules/rand.go b/vendor/github.com/securego/gosec/v2/rules/rand.go
index a1d3508a..e41969f7 100644
--- a/vendor/github.com/securego/gosec/v2/rules/rand.go
+++ b/vendor/github.com/securego/gosec/v2/rules/rand.go
@@ -30,10 +30,10 @@ func NewWeakRandCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
rule := &weakRand{newCallListRule(id,
"Use of weak random number generator (math/rand or math/rand/v2 instead of crypto/rand)",
issue.High, issue.Medium)}
- rule.AddAll("math/rand", "New", "Read", "Float32", "Float64", "Int", "Int31", "Int31n",
- "Int63", "Int63n", "Intn", "NormFloat64", "Uint32", "Uint64")
- rule.AddAll("math/rand/v2", "New", "Float32", "Float64", "Int", "Int32", "Int32N",
- "Int64", "Int64N", "IntN", "N", "NormFloat64", "Uint32", "Uint32N", "Uint64", "Uint64N", "UintN")
+ rule.AddAll("math/rand", "New", "Read", "ExpFloat64", "Float32", "Float64", "Int", "Int31", "Int31n",
+ "Int63", "Int63n", "Intn", "NormFloat64", "Perm", "Shuffle", "Uint32", "Uint64")
+ rule.AddAll("math/rand/v2", "New", "ExpFloat64", "Float32", "Float64", "Int", "Int32", "Int32N",
+ "Int64", "Int64N", "IntN", "N", "NormFloat64", "Perm", "Shuffle", "Uint", "Uint32", "Uint32N", "Uint64", "Uint64N", "UintN")
return rule, []ast.Node{(*ast.CallExpr)(nil)}
}
diff --git a/vendor/github.com/securego/gosec/v2/rules/secret_serialization.go b/vendor/github.com/securego/gosec/v2/rules/secret_serialization.go
index 06473faa..6389309c 100644
--- a/vendor/github.com/securego/gosec/v2/rules/secret_serialization.go
+++ b/vendor/github.com/securego/gosec/v2/rules/secret_serialization.go
@@ -21,10 +21,11 @@ type secretSerialization struct {
}
type formatSpec struct {
- name string
- tagKey string
- functionSinks []functionSink
- methodSinks []methodSink
+ name string
+ tagKey string
+ marshalerMethod string // e.g. "MarshalJSON"; empty if no standard interface exists
+ functionSinks []functionSink
+ methodSinks []methodSink
}
type functionSink struct {
@@ -44,15 +45,16 @@ type typeAnalysisCacheKey struct {
}
type sensitiveFieldMatch struct {
- fieldName string
- jsonKey string
- found bool
+ fieldName string
+ serializedKey string
+ found bool
}
var g117Formats = []formatSpec{
{
- name: "json",
- tagKey: "json",
+ name: "JSON",
+ tagKey: "json",
+ marshalerMethod: "MarshalJSON",
functionSinks: []functionSink{
{pkgPath: "encoding/json", names: []string{"Marshal", "MarshalIndent"}},
},
@@ -61,8 +63,9 @@ var g117Formats = []formatSpec{
},
},
{
- name: "yaml",
- tagKey: "yaml",
+ name: "YAML",
+ tagKey: "yaml",
+ marshalerMethod: "MarshalYAML",
functionSinks: []functionSink{
{pkgPath: "go.yaml.in/yaml/v3", names: []string{"Marshal"}},
{pkgPath: "gopkg.in/yaml.v3", names: []string{"Marshal"}},
@@ -76,8 +79,9 @@ var g117Formats = []formatSpec{
},
},
{
- name: "xml",
- tagKey: "xml",
+ name: "XML",
+ tagKey: "xml",
+ marshalerMethod: "MarshalXML",
functionSinks: []functionSink{
{pkgPath: "encoding/xml", names: []string{"Marshal", "MarshalIndent"}},
},
@@ -86,7 +90,7 @@ var g117Formats = []formatSpec{
},
},
{
- name: "toml",
+ name: "TOML",
tagKey: "toml",
functionSinks: []functionSink{
{pkgPath: "github.com/pelletier/go-toml", names: []string{"Marshal"}},
@@ -111,17 +115,146 @@ func (r *secretSerialization) Match(n ast.Node, ctx *gosec.Context) (*issue.Issu
return nil, nil
}
+ if isInsideCustomMarshaler(callExpr, ctx) {
+ return nil, nil
+ }
+
typ := ctx.Info.TypeOf(serializedArg)
if typ == nil {
return nil, nil
}
- if match := r.findSensitiveFieldForType(typ, format.tagKey); match.found {
- msg := fmt.Sprintf("Marshaled struct field %q (JSON key %q) matches secret pattern", match.fieldName, match.jsonKey)
- return ctx.NewIssue(callExpr, r.ID(), msg, r.Severity, r.Confidence), nil
+ if typeImplementsMarshaler(typ, format.marshalerMethod) {
+ return nil, nil
+ }
+
+ match := r.findSensitiveFieldForType(typ, format.tagKey)
+ if !match.found {
+ return nil, nil
+ }
+
+ if compositeLitFieldIsTransformed(serializedArg, match.fieldName) {
+ return nil, nil
+ }
+
+ msg := fmt.Sprintf("Marshaled struct field %q (%s key %q) matches secret pattern", match.fieldName, format.name, match.serializedKey)
+ return ctx.NewIssue(callExpr, r.ID(), msg, r.Severity, r.Confidence), nil
+}
+
+// customMarshalerMethods lists method names that indicate a custom marshaler
+// implementation. When a marshal call occurs inside one of these methods, the
+// developer is explicitly controlling serialization, so G117 should not flag it.
+var customMarshalerMethods = map[string]bool{
+ "MarshalJSON": true,
+ "MarshalYAML": true,
+ "MarshalXML": true,
+ "MarshalText": true,
+ "MarshalTOML": true,
+ "MarshalBSON": true,
+}
+
+// isInsideCustomMarshaler reports whether callExpr is located inside a method
+// whose name matches a known custom marshaler (e.g. MarshalJSON).
+func isInsideCustomMarshaler(callExpr *ast.CallExpr, ctx *gosec.Context) bool {
+ if ctx.Root == nil {
+ return false
+ }
+
+ pos := callExpr.Pos()
+ var found bool
+
+ ast.Inspect(ctx.Root, func(n ast.Node) bool {
+ if found {
+ return false
+ }
+ funcDecl, ok := n.(*ast.FuncDecl)
+ if !ok || funcDecl.Body == nil {
+ return true
+ }
+ // Check if the call is inside this function body.
+ if pos < funcDecl.Body.Pos() || pos >= funcDecl.Body.End() {
+ return true
+ }
+ // Must be a method (has a receiver) with a recognized marshaler name.
+ if funcDecl.Recv != nil && funcDecl.Recv.NumFields() > 0 {
+ if customMarshalerMethods[funcDecl.Name.Name] {
+ found = true
+ }
+ }
+ return false
+ })
+
+ return found
+}
+
+// typeImplementsMarshaler reports whether typ (or its element type for
+// containers) has a method with the given name, indicating it implements a
+// custom marshaler interface (e.g. json.Marshaler). When a type has a custom
+// marshaler, the serialization library calls that method instead of serializing
+// fields directly, making struct field analysis irrelevant.
+func typeImplementsMarshaler(typ types.Type, methodName string) bool {
+ if methodName == "" {
+ return false
+ }
+ named := elementNamedType(typ)
+ if named == nil {
+ return false
+ }
+ // Check both value and pointer receiver methods via the pointer method set,
+ // which is a superset of the value method set.
+ mset := types.NewMethodSet(types.NewPointer(named))
+ for i := 0; i < mset.Len(); i++ {
+ if mset.At(i).Obj().Name() == methodName {
+ return true
+ }
+ }
+ return false
+}
+
+// elementNamedType unwraps pointers, slices, arrays, and maps to find the
+// innermost Named type. Returns nil if no Named type is found.
+func elementNamedType(typ types.Type) *types.Named {
+ switch t := typ.(type) {
+ case *types.Named:
+ return t
+ case *types.Pointer:
+ return elementNamedType(t.Elem())
+ case *types.Slice:
+ return elementNamedType(t.Elem())
+ case *types.Array:
+ return elementNamedType(t.Elem())
+ case *types.Map:
+ return elementNamedType(t.Elem())
}
+ return nil
+}
- return nil, nil
+// compositeLitFieldIsTransformed checks whether expr is a composite literal
+// in which the given field name is assigned a function call result. A function
+// call indicates the value is being transformed (e.g. masked or redacted)
+// before serialization.
+func compositeLitFieldIsTransformed(expr ast.Expr, fieldName string) bool {
+ // Unwrap address-of operator: &Struct{...}
+ if unary, ok := expr.(*ast.UnaryExpr); ok {
+ expr = unary.X
+ }
+ lit, ok := expr.(*ast.CompositeLit)
+ if !ok {
+ return false
+ }
+ for _, elt := range lit.Elts {
+ kv, ok := elt.(*ast.KeyValueExpr)
+ if !ok {
+ continue
+ }
+ ident, ok := kv.Key.(*ast.Ident)
+ if !ok || ident.Name != fieldName {
+ continue
+ }
+ _, isCall := kv.Value.(*ast.CallExpr)
+ return isCall
+ }
+ return false
}
func isNamedTypeInPackage(typ types.Type, pkgPath, typeName string) bool {
@@ -382,7 +515,7 @@ func (r *secretSerialization) findSensitiveSerializedField(st *types.Struct, tag
}
if gosec.RegexMatchWithCache(r.pattern, field.Name()) || gosec.RegexMatchWithCache(r.pattern, effectiveKey) {
- return sensitiveFieldMatch{fieldName: field.Name(), jsonKey: effectiveKey, found: true}
+ return sensitiveFieldMatch{fieldName: field.Name(), serializedKey: effectiveKey, found: true}
}
}
diff --git a/vendor/github.com/securego/gosec/v2/rules/tls.go b/vendor/github.com/securego/gosec/v2/rules/tls.go
index 96b243df..6f7cb399 100644
--- a/vendor/github.com/securego/gosec/v2/rules/tls.go
+++ b/vendor/github.com/securego/gosec/v2/rules/tls.go
@@ -236,22 +236,28 @@ func (t *insecureConfigTLS) findDefinition(obj types.Object, c *gosec.Context) a
return initializer
}
+func (t *insecureConfigTLS) isSafeDefault() bool {
+ major, minor, _ := gosec.GoVersion()
+ return major > 1 || (major == 1 && minor >= 18)
+}
+
func (t *insecureConfigTLS) checkVersion(n ast.Node, c *gosec.Context) *issue.Issue {
- // Flag explicitly low MinVersion (including explicit 0)
+ // Flag explicitly low MinVersion.
+ // Since Go 1.18+, MinVersion 0 means "use default" which is
+ // TLS 1.2 — safe and not worth flagging.
if t.minVersionSet && t.actualMinVersion < t.MinVersion {
+ if t.actualMinVersion == 0 && t.isSafeDefault() {
+ return nil
+ }
return c.NewIssue(n, t.ID(), "TLS MinVersion too low.", issue.High, issue.High)
}
- // Handle MaxVersion
+ // Handle MaxVersion.
+ // MaxVersion 0 means "use latest" which is always safe.
if t.maxVersionSet {
- // Special case for explicit MaxVersion: 0 (default latest) - suppress warning if MinVersion is securely set
if t.actualMaxVersion == 0 {
- if t.minVersionSet && t.actualMinVersion >= t.MinVersion {
- return nil
- }
- // Otherwise treat explicit 0 as potentially insecure (fall through to flag)
+ return nil
}
- // Flag if explicitly capped too low (non-zero low values always flagged)
if t.actualMaxVersion < t.MaxVersion {
return c.NewIssue(n, t.ID(), "TLS MaxVersion too low.", issue.High, issue.High)
}
@@ -271,6 +277,7 @@ func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*issue.Issue, e
if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil {
actualType := c.Info.TypeOf(complit.Type)
if actualType != nil && actualType.String() == t.requiredType {
+ defer t.resetVersion()
for _, elt := range complit.Elts {
if issue := t.processTLSConf(elt, c); issue != nil {
return issue, nil
@@ -279,7 +286,6 @@ func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*issue.Issue, e
if issue := t.checkVersion(complit, c); issue != nil {
return issue, nil
}
- t.resetVersion()
return nil, nil
}
}
diff --git a/vendor/github.com/securego/gosec/v2/taint/taint.go b/vendor/github.com/securego/gosec/v2/taint/taint.go
index d53b14f2..fab64ccc 100644
--- a/vendor/github.com/securego/gosec/v2/taint/taint.go
+++ b/vendor/github.com/securego/gosec/v2/taint/taint.go
@@ -23,6 +23,12 @@ import (
// maxTaintDepth limits recursion depth to prevent stack overflow on large codebases
const maxTaintDepth = 50
+// maxCallerEdges caps the number of incoming call graph edges examined per function
+// in isParameterTainted. CHA over-approximates call graphs (every interface method
+// call fans out to ALL implementations), so a function can have thousands of callers.
+// Real taint flows come from direct/nearby callers, not the 33rd+ CHA-generated edge.
+const maxCallerEdges = 32
+
// isContextType checks if a type is context.Context.
// context.Context is a control-flow mechanism (deadlines, cancellation, request-scoped values)
// that does not carry user-controlled data relevant to taint sinks like XSS.
@@ -211,14 +217,21 @@ type Config struct {
}
// Analyzer performs taint analysis on SSA programs.
+// paramKey identifies a specific parameter of a function for memoization.
+type paramKey struct {
+ fn *ssa.Function
+ paramIdx int
+}
+
type Analyzer struct {
- config *Config
- sources map[string]Source // keyed by full type string
- funcSrcs map[string]Source // function sources keyed by "pkg.Func"
- sinks map[string]Sink // keyed by full function string
- sanitizers map[string]struct{} // keyed by full function string
- callGraph *callgraph.Graph
- prog *ssa.Program // set at Analyze time for ArgTypeGuards resolution
+ config *Config
+ sources map[string]Source // keyed by full type string
+ funcSrcs map[string]Source // function sources keyed by "pkg.Func"
+ sinks map[string]Sink // keyed by full function string
+ sanitizers map[string]struct{} // keyed by full function string
+ callGraph *callgraph.Graph
+ prog *ssa.Program // set at Analyze time for ArgTypeGuards resolution
+ paramTaintCache map[paramKey]bool // caches true results from isParameterTainted
}
// SetCallGraph injects a precomputed call graph.
@@ -309,6 +322,8 @@ func (a *Analyzer) Analyze(prog *ssa.Program, srcFuncs []*ssa.Function) []Result
a.callGraph = cha.CallGraph(prog)
}
+ a.paramTaintCache = make(map[paramKey]bool)
+
var results []Result
// Find all sink calls in the program
@@ -316,6 +331,8 @@ func (a *Analyzer) Analyze(prog *ssa.Program, srcFuncs []*ssa.Function) []Result
results = append(results, a.analyzeFunctionSinks(fn)...)
}
+ a.paramTaintCache = nil
+
return results
}
@@ -794,6 +811,33 @@ func (a *Analyzer) isSourceType(t types.Type) bool {
return false
}
+// mayHaveExternalCallers reports whether fn could be invoked by code outside
+// the analyzed package — code that is invisible to the call graph.
+//
+// Exported bare functions (non-methods) are the primary case: frameworks
+// register them via dynamic dispatch that CHA cannot resolve, so the call
+// graph may lack edges even though the function IS called at runtime.
+//
+// Methods with a receiver are excluded because CHA resolves interface dispatch
+// to concrete methods, so their callers are generally visible in the graph.
+// Unexported functions are only callable within the package, and the call graph
+// covers intra-package calls comprehensively.
+func mayHaveExternalCallers(fn *ssa.Function) bool {
+ if fn.Signature == nil {
+ return false
+ }
+ // Methods — CHA handles interface dispatch; callers are visible.
+ if fn.Signature.Recv() != nil {
+ return false
+ }
+ // Closures / anonymous functions are never exported.
+ if fn.Parent() != nil {
+ return false
+ }
+ // Exported bare function — may be called by external frameworks.
+ return token.IsExported(fn.Name())
+}
+
// isSourceFuncCall checks if a call invokes a known source function
// (a function explicitly configured as producing tainted data, e.g., os.Getenv).
func (a *Analyzer) isSourceFuncCall(call *ssa.Call) bool {
@@ -824,30 +868,65 @@ func (a *Analyzer) isParameterTainted(param *ssa.Parameter, fn *ssa.Function, vi
return false
}
- // Check if parameter type is a source type.
- // This is the ONLY place where type-based source matching should trigger
- // automatic taint — because parameters represent data flowing IN from
- // external callers we don't control.
- if a.isSourceType(param.Type()) {
- return true
+ // Resolve paramIdx early so we can use it for cache lookups.
+ paramIdx := -1
+ for i, p := range fn.Params {
+ if p == param {
+ paramIdx = i
+ break
+ }
+ }
+
+ // Check memoization cache (only true results are cached).
+ if paramIdx >= 0 && a.paramTaintCache != nil {
+ key := paramKey{fn: fn, paramIdx: paramIdx}
+ if a.paramTaintCache[key] {
+ return true
+ }
}
// Use call graph to find callers and check their arguments
if a.callGraph == nil {
+ // No call graph: fall back to type-based auto-taint for source-typed params
+ // (conservative — may produce false positives, but we have no callee info).
+ if a.isSourceType(param.Type()) {
+ if paramIdx >= 0 && a.paramTaintCache != nil {
+ a.paramTaintCache[paramKey{fn: fn, paramIdx: paramIdx}] = true
+ }
+ return true
+ }
return false
}
node := a.callGraph.Nodes[fn]
- if node == nil {
- return false
- }
- paramIdx := -1
- for i, p := range fn.Params {
- if p == param {
- paramIdx = i
- break
+ // Check if parameter type is a configured source type.
+ //
+ // Strategy:
+ // 1. No callers in call graph → definite entry point → auto-taint.
+ // 2. Exported bare function → may have invisible external callers
+ // (framework dispatch) → auto-taint to avoid false negatives.
+ // 3. Has callers, not exported bare func → fall through to caller check.
+ //
+ // Case 2 addresses a class of false negatives where an internal caller
+ // with safe args suppresses taint for an exported entry point that is
+ // also called externally by a framework (issue #1629 + Barry review).
+ // Methods are excluded because CHA resolves interface dispatch, making
+ // their callers visible in the call graph.
+ if a.isSourceType(param.Type()) {
+ isEntryPoint := (node == nil || len(node.In) == 0)
+ if isEntryPoint || mayHaveExternalCallers(fn) {
+ if paramIdx >= 0 && a.paramTaintCache != nil {
+ a.paramTaintCache[paramKey{fn: fn, paramIdx: paramIdx}] = true
+ }
+ return true
}
+ // Has known callers and is not a handler — fall through to verify
+ // taint via those callers.
+ }
+
+ if node == nil {
+ return false
}
if paramIdx < 0 {
@@ -867,8 +946,14 @@ func (a *Analyzer) isParameterTainted(param *ssa.Parameter, fn *ssa.Function, vi
adjustedIdx = paramIdx
}
- // Check each caller
+ // Check each caller, capping at maxCallerEdges to avoid combinatorial
+ // explosion from CHA over-approximation of interface method calls.
+ edgesChecked := 0
for _, inEdge := range node.In {
+ if edgesChecked >= maxCallerEdges {
+ break
+ }
+
site := inEdge.Site
if site == nil {
continue
@@ -877,7 +962,11 @@ func (a *Analyzer) isParameterTainted(param *ssa.Parameter, fn *ssa.Function, vi
callArgs := site.Common().Args
if adjustedIdx < len(callArgs) {
+ edgesChecked++
if a.isTainted(callArgs[adjustedIdx], inEdge.Caller.Func, visited, depth+1) {
+ if a.paramTaintCache != nil {
+ a.paramTaintCache[paramKey{fn: fn, paramIdx: paramIdx}] = true
+ }
return true
}
}
@@ -1018,6 +1107,10 @@ func (a *Analyzer) isFieldTaintedOnValue(v ssa.Value, fieldIdx int, fn *ssa.Func
case *ssa.Alloc:
return a.isFieldOfAllocTainted(val, fieldIdx, fn, visited, depth)
case *ssa.Phi:
+ if visited[v] {
+ return false
+ }
+ visited[v] = true
for _, edge := range val.Edges {
if a.isFieldTaintedOnValue(edge, fieldIdx, fn, visited, depth+1) {
return true
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_darwin.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_darwin.go
index d3b6dbc5..847a9162 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_darwin.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_darwin.go
@@ -143,7 +143,7 @@ func perCPUTimes(sys *common.SystemLib) ([]TimesStat, error) {
var cpuload *hostCpuLoadInfoData
status := sys.HostProcessorInfo(sys.MachHostSelf(), processorCpuLoadInfo,
- &ncpu, uintptr(unsafe.Pointer(&cpuload)), &count)
+ &ncpu, unsafe.Pointer(&cpuload), &count)
if status != common.KERN_SUCCESS {
return nil, fmt.Errorf("host_processor_info error=%d", status)
@@ -177,7 +177,7 @@ func allCPUTimes(sys *common.SystemLib) ([]TimesStat, error) {
count := uint32(cpuStateMax)
status := sys.HostStatistics(sys.MachHostSelf(), common.HOST_CPU_LOAD_INFO,
- uintptr(unsafe.Pointer(&cpuload)), &count)
+ unsafe.Pointer(&cpuload), &count)
if status != common.KERN_SUCCESS {
return nil, fmt.Errorf("host_statistics error=%d", status)
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_freebsd.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_freebsd.go
index 3e0aeb26..38abcd0e 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_freebsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_freebsd.go
@@ -81,6 +81,9 @@ func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
if err != nil {
return nil, err
}
+ if len(buf) < int(unsafe.Sizeof(cpuTimes{})) {
+ return nil, fmt.Errorf("unexpected size: kern.cp_time, %d", len(buf))
+ }
times := (*cpuTimes)(unsafe.Pointer(&buf[0]))
return []TimesStat{*timeStat("cpu-total", times)}, nil
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd.go
index 9e23edb6..bb383129 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd.go
@@ -44,6 +44,9 @@ func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
if err != nil {
return ret, err
}
+ if len(buf) < int(unsafe.Sizeof(cpuTimes{})) {
+ return ret, fmt.Errorf("unexpected size: kern.cp_time, %d", len(buf))
+ }
times := (*cpuTimes)(unsafe.Pointer(&buf[0]))
ret = append(ret, TimesStat{
CPU: "cpu-total",
@@ -68,6 +71,9 @@ func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
if err != nil {
return ret, err
}
+ if len(buf) < int(unsafe.Sizeof(cpuTimes{})) {
+ continue
+ }
stats := (*cpuTimes)(unsafe.Pointer(&buf[0]))
ret = append(ret, TimesStat{
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_openbsd.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_openbsd.go
index 9b37d296..01654339 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_openbsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_openbsd.go
@@ -62,6 +62,9 @@ func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
if err != nil {
return ret, err
}
+ if len(buf) < int(unsafe.Sizeof(cpuTimes{})) {
+ return ret, fmt.Errorf("unexpected size: kern.cp_time, %d", len(buf))
+ }
times := (*cpuTimes)(unsafe.Pointer(&buf[0]))
ret = append(ret, TimesStat{
CPU: "cpu-total",
@@ -86,6 +89,9 @@ func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
if err != nil {
return ret, err
}
+ if len(buf) < int(unsafe.Sizeof(cpuStats{})) {
+ continue
+ }
stats := (*cpuStats)(unsafe.Pointer(&buf[0]))
if (stats.Flags & cpuOnline) == 0 {
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_windows.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_windows.go
index c15a085b..5a8a344a 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_windows.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_windows.go
@@ -104,14 +104,78 @@ func Times(percpu bool) ([]TimesStat, error) {
}
func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
+ // Get the CPU performance counters per processor via Windows API
+ stats, err := perfInfo()
+ if err == nil && len(stats) == 0 {
+ err = errors.New("no processor performance information returned")
+ }
+ if err != nil {
+ if percpu {
+ return nil, err
+ }
+ // perfInfo relies on the undocumented NtQuerySystemInformation, which
+ // may be unavailable in restricted environments. Fall back to the
+ // public GetSystemTimes for the total rather than failing outright.
+ return systemTimes()
+ }
+
if percpu {
- return perCPUTimes()
+ ret := make([]TimesStat, 0, len(stats))
+ for core, v := range stats {
+ c := TimesStat{
+ CPU: fmt.Sprintf("cpu%d", core),
+ User: float64(v.UserTime) / ClocksPerSec,
+ System: float64(v.KernelTime-v.IdleTime) / ClocksPerSec,
+ Idle: float64(v.IdleTime) / ClocksPerSec,
+ Irq: float64(v.InterruptTime) / ClocksPerSec,
+ }
+ ret = append(ret, c)
+ }
+ return ret, nil
+ }
+
+ // Accumulate the times over all CPUs as GetSystemTimes() will only return
+ // the counters for the current processor group. This causes issues for
+ // machines with more than 64 logical processors when the current thread is
+ // switched to another processor group as then the counters are not
+ // monotonic anymore.
+ //
+ // Do all arithmetic on the integer tick counts and convert to float64 only
+ // once. Converting each counter first loses precision on large counters and
+ // can make the returned values non-monotonic. See issue #2110.
+ var idle, kernel, user, interrupt int64
+ for _, v := range stats {
+ idle += v.IdleTime
+ kernel += v.KernelTime
+ user += v.UserTime
+ interrupt += v.InterruptTime
}
- var ret []TimesStat
- var lpIdleTime common.FILETIME
- var lpKernelTime common.FILETIME
- var lpUserTime common.FILETIME
+ return []TimesStat{
+ {
+ CPU: "cpu-total",
+ User: float64(user) / ClocksPerSec,
+ System: float64(kernel-idle) / ClocksPerSec, // kernel time includes idle time
+ Idle: float64(idle) / ClocksPerSec,
+ Irq: float64(interrupt) / ClocksPerSec,
+ },
+ }, nil
+}
+
+// systemTimes returns the combined CPU times reported by GetSystemTimes.
+//
+// This is only a fallback for TimesWithContext(ctx, false): GetSystemTimes is a
+// documented public API but returns the counters of the calling thread's
+// processor group only, so on hosts with more than 64 logical processors the
+// values are not monotonic once the thread is migrated to another group. It
+// also cannot report Irq, which is left at zero here.
+//
+// Whether perfInfo works is a property of the environment, so in practice a
+// process stays on one path for its whole lifetime. Should perfInfo fail only
+// intermittently on a multi-group host, the two paths cover a different number
+// of processors, and Percent may report one bogus sample before recovering.
+func systemTimes() ([]TimesStat, error) {
+ var lpIdleTime, lpKernelTime, lpUserTime common.FILETIME
// GetSystemTimes returns 0 for error, in which case we check err,
// see https://pkg.go.dev/golang.org/x/sys/windows#LazyProc.Call
r, _, err := common.ProcGetSystemTimes.Call(
@@ -122,20 +186,19 @@ func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
return nil, err
}
- LOT := float64(0.0000001)
- HIT := (LOT * 4294967296.0)
- idle := ((HIT * float64(lpIdleTime.DwHighDateTime)) + (LOT * float64(lpIdleTime.DwLowDateTime)))
- user := ((HIT * float64(lpUserTime.DwHighDateTime)) + (LOT * float64(lpUserTime.DwLowDateTime)))
- kernel := ((HIT * float64(lpKernelTime.DwHighDateTime)) + (LOT * float64(lpKernelTime.DwLowDateTime)))
- system := (kernel - idle)
-
- ret = append(ret, TimesStat{
- CPU: "cpu-total",
- Idle: float64(idle),
- User: float64(user),
- System: float64(system),
- })
- return ret, nil
+ // See the note on integer arithmetic in TimesWithContext and issue #2110.
+ idle := uint64(lpIdleTime.DwHighDateTime)<<32 | uint64(lpIdleTime.DwLowDateTime)
+ user := uint64(lpUserTime.DwHighDateTime)<<32 | uint64(lpUserTime.DwLowDateTime)
+ kernel := uint64(lpKernelTime.DwHighDateTime)<<32 | uint64(lpKernelTime.DwLowDateTime)
+
+ return []TimesStat{
+ {
+ CPU: "cpu-total",
+ User: float64(user) / ClocksPerSec,
+ System: float64(kernel-idle) / ClocksPerSec, // kernel time includes idle time
+ Idle: float64(idle) / ClocksPerSec,
+ },
+ }, nil
}
func Info() ([]InfoStat, error) {
@@ -242,35 +305,22 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
return ret, nil
}
-// perCPUTimes returns times stat per cpu, per core and overall for all CPUs
-func perCPUTimes() ([]TimesStat, error) {
- var ret []TimesStat
- stats, err := perfInfo()
- if err != nil {
- return nil, err
- }
- for core, v := range stats {
- c := TimesStat{
- CPU: fmt.Sprintf("cpu%d", core),
- User: float64(v.UserTime) / ClocksPerSec,
- System: float64(v.KernelTime-v.IdleTime) / ClocksPerSec,
- Idle: float64(v.IdleTime) / ClocksPerSec,
- Irq: float64(v.InterruptTime) / ClocksPerSec,
- }
- ret = append(ret, c)
- }
- return ret, nil
-}
-
// makes call to Windows API function to retrieve performance information for each core
func perfInfo() ([]win32_SystemProcessorPerformanceInformation, error) {
// On hosts with more than 64 logical CPUs Windows splits CPUs into Processor Groups
// (up to 64 logical CPUs per group). The non-Ex NtQuerySystemInformation only returns
// data for the calling thread's group, so whenever the Ex variant is available we
// iterate every active group and concatenate the results. See issue #887.
- if common.ProcNtQuerySystemInformationEx.Find() == nil {
+ //
+ // Every proc is resolved with Find before it is used: LazyProc.Call panics when it
+ // cannot resolve, and a panic would take the caller's process down instead of
+ // letting TimesWithContext fall back to GetSystemTimes.
+ if common.ProcNtQuerySystemInformationEx.Find() == nil && procGetActiveProcessorGroupCount.Find() == nil {
return perfInfoAllGroups()
}
+ if err := common.ProcNtQuerySystemInformation.Find(); err != nil {
+ return nil, err
+ }
return perfInfoSingleGroup()
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go
index caa1b8d9..2cf72875 100644
--- a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go
@@ -27,16 +27,37 @@ const (
SystemLibPath = "/usr/lib/libSystem.B.dylib"
)
+// Library handles are opened once and shared for the process lifetime.
+// Opening and closing them on every call causes SIGBUS/SIGSEGV crashes because
+// the Go runtime (GC, timers) can interact with invalidated library handles
+// after Dlclose. Sharing also keeps the resolved-symbol cache in fnMap warm,
+// so a symbol lookup is not repeated on every call.
+// See: https://github.com/shirou/gopsutil/issues/1832
+var (
+ libCacheMu sync.Mutex
+ libCache = make(map[string]*library)
+)
+
func newLibrary(path string) (*library, error) {
- lib, err := purego.Dlopen(path, purego.RTLD_LAZY|purego.RTLD_GLOBAL)
+ libCacheMu.Lock()
+ defer libCacheMu.Unlock()
+
+ if lib, ok := libCache[path]; ok {
+ return lib, nil
+ }
+
+ handle, err := purego.Dlopen(path, purego.RTLD_LAZY|purego.RTLD_GLOBAL)
if err != nil {
return nil, err
}
- return &library{
- handle: lib,
+ lib := &library{
+ handle: handle,
fnMap: make(map[string]any),
- }, nil
+ }
+ libCache[path] = lib
+
+ return lib, nil
}
func (lib *library) Dlsym(symbol string) (uintptr, error) {
@@ -69,9 +90,10 @@ func getFunc[T any](lib *library, symbol string) T {
return dlfun.fn
}
-func (lib *library) Close() {
- purego.Dlclose(lib.handle)
-}
+// Close is a no-op, kept so that existing defer-Close call sites keep working.
+// Library handles are shared process-wide and are deliberately never unloaded;
+// see newLibrary for why.
+func (*library) Close() {}
type dlFunc[T any] struct {
sym string
@@ -103,12 +125,12 @@ func (c *CoreFoundationLib) CFGetTypeID(cf uintptr) int64 {
return fn(cf)
}
-func (c *CoreFoundationLib) CFNumberCreate(allocator uintptr, theType int64, valuePtr uintptr) unsafe.Pointer {
+func (c *CoreFoundationLib) CFNumberCreate(allocator uintptr, theType int64, valuePtr unsafe.Pointer) unsafe.Pointer {
fn := getFunc[CFNumberCreateFunc](c.library, "CFNumberCreate")
return fn(allocator, theType, valuePtr)
}
-func (c *CoreFoundationLib) CFNumberGetValue(num uintptr, theType int64, valuePtr uintptr) bool {
+func (c *CoreFoundationLib) CFNumberGetValue(num uintptr, theType int64, valuePtr unsafe.Pointer) bool {
fn := getFunc[CFNumberGetValueFunc](c.library, "CFNumberGetValue")
return fn(num, theType, valuePtr)
}
@@ -247,7 +269,9 @@ func (l *IOKitLib) IOObjectRelease(object uint32) int32 {
return fn(object)
}
-func (l *IOKitLib) IOConnectCallStructMethod(connection, selector uint32, inputStruct, inputStructCnt, outputStruct uintptr, outputStructCnt *uintptr) int32 {
+func (l *IOKitLib) IOConnectCallStructMethod(connection, selector uint32, inputStruct unsafe.Pointer, inputStructCnt uintptr,
+ outputStruct unsafe.Pointer, outputStructCnt *uintptr,
+) int32 {
fn := getFunc[IOConnectCallStructMethodFunc](l.library, "IOConnectCallStructMethod")
return fn(connection, selector, inputStruct, inputStructCnt, outputStruct, outputStructCnt)
}
@@ -294,14 +318,14 @@ func NewSystemLib() (*SystemLib, error) {
return &SystemLib{library}, nil
}
-func (s *SystemLib) HostProcessorInfo(host uint32, flavor int32, outProcessorCount *uint32, outProcessorInfo uintptr,
+func (s *SystemLib) HostProcessorInfo(host uint32, flavor int32, outProcessorCount *uint32, outProcessorInfo unsafe.Pointer,
outProcessorInfoCnt *uint32,
) int32 {
fn := getFunc[HostProcessorInfoFunc](s.library, "host_processor_info")
return fn(host, flavor, outProcessorCount, outProcessorInfo, outProcessorInfoCnt)
}
-func (s *SystemLib) HostStatistics(host uint32, flavor int32, hostInfoOut uintptr, hostInfoOutCnt *uint32) int32 {
+func (s *SystemLib) HostStatistics(host uint32, flavor int32, hostInfoOut unsafe.Pointer, hostInfoOutCnt *uint32) int32 {
fn := getFunc[HostStatisticsFunc](s.library, "host_statistics")
return fn(host, flavor, hostInfoOut, hostInfoOutCnt)
}
@@ -316,7 +340,7 @@ func (s *SystemLib) MachTaskSelf() uint32 {
return fn()
}
-func (s *SystemLib) MachTimeBaseInfo(info uintptr) int32 {
+func (s *SystemLib) MachTimeBaseInfo(info unsafe.Pointer) int32 {
fn := getFunc[MachTimeBaseInfoFunc](s.library, "mach_timebase_info")
return fn(info)
}
@@ -326,21 +350,51 @@ func (s *SystemLib) VMDeallocate(targetTask uint32, vmAddress, vmSize uintptr) i
return fn(targetTask, vmAddress, vmSize)
}
-func (s *SystemLib) ProcPidPath(pid int32, buffer uintptr, bufferSize uint32) int32 {
+func (s *SystemLib) ProcPidPath(pid int32, buffer unsafe.Pointer, bufferSize uint32) int32 {
fn := getFunc[ProcPidPathFunc](s.library, "proc_pidpath")
return fn(pid, buffer, bufferSize)
}
-func (s *SystemLib) ProcPidInfo(pid, flavor int32, arg uint64, buffer uintptr, bufferSize int32) int32 {
+func (s *SystemLib) ProcPidInfo(pid, flavor int32, arg uint64, buffer unsafe.Pointer, bufferSize int32) int32 {
fn := getFunc[ProcPidInfoFunc](s.library, "proc_pidinfo")
return fn(pid, flavor, arg, buffer, bufferSize)
}
+func (s *SystemLib) ProcPidRusage(pid, flavor int32, buffer unsafe.Pointer) int32 {
+ fn := getFunc[ProcPidRusageFunc](s.library, "proc_pid_rusage")
+ return fn(pid, flavor, buffer)
+}
+
+// ErrnoLocation returns a pointer to the calling OS thread's errno, as given by
+// libc's __error(). The pointer is thread-local, so callers must hold
+// runtime.LockOSThread() across this call, the libc call being checked, and the
+// dereference of the returned pointer.
+//
+// Resolve the pointer *before* the libc call whose errno is to be inspected.
+// Resolving a symbol performs a dlsym and allocates, and either may overwrite
+// errno; doing it afterwards would race with the value being read.
+func (s *SystemLib) ErrnoLocation() *int32 {
+ fn := getFunc[ErrnoFunc](s.library, "__error")
+ return fn()
+}
+
// status codes
const (
KERN_SUCCESS = 0
)
+// Arguments that point at Go memory are declared as unsafe.Pointer, a Go
+// pointer type, or a slice -- never as uintptr. purego maps uintptr to
+// uintptr_t, i.e. a plain integer: it neither keeps the pointee alive nor makes
+// it escape, so a Go local stays on the goroutine stack and the address goes
+// stale the moment the stack grows. Every such call then reads or writes the old
+// stack and silently sees or produces zeroes. The other kinds are passed through
+// reflect.Value.Pointer() and stay reachable for the duration of the call.
+//
+// uintptr remains correct for handles that are not Go memory: CoreFoundation and
+// IOKit object references, mach ports, addresses of dylib data symbols obtained
+// through Dlsym, and kernel-allocated vm addresses.
+
// IOKit types and constants.
type (
IOServiceGetMatchingServiceFunc func(mainPort uint32, matching uintptr) uint32
@@ -355,7 +409,8 @@ type (
IORegistryEntryCreateCFPropertiesFunc func(entry uint32, properties unsafe.Pointer, allocator uintptr, options uint32) int32
IOObjectConformsToFunc func(object uint32, className string) bool
IOObjectReleaseFunc func(object uint32) int32
- IOConnectCallStructMethodFunc func(connection, selector uint32, inputStruct, inputStructCnt, outputStruct uintptr, outputStructCnt *uintptr) int32
+ IOConnectCallStructMethodFunc func(connection, selector uint32, inputStruct unsafe.Pointer, inputStructCnt uintptr,
+ outputStruct unsafe.Pointer, outputStructCnt *uintptr) int32
IOHIDEventSystemClientCreateFunc func(allocator uintptr) unsafe.Pointer
IOHIDEventSystemClientSetMatchingFunc func(client, match uintptr) int32
@@ -380,10 +435,14 @@ const (
)
// CoreFoundation types and constants.
+//
+// valuePtr on CFNumberCreate and CFNumberGetValue points at a caller-owned Go
+// value that CoreFoundation reads from or writes into, hence unsafe.Pointer; see
+// the note above the IOKit function types.
type (
CFGetTypeIDFunc func(cf uintptr) int64
- CFNumberCreateFunc func(allocator uintptr, theType int64, valuePtr uintptr) unsafe.Pointer
- CFNumberGetValueFunc func(num uintptr, theType int64, valuePtr uintptr) bool
+ CFNumberCreateFunc func(allocator uintptr, theType int64, valuePtr unsafe.Pointer) unsafe.Pointer
+ CFNumberGetValueFunc func(num uintptr, theType int64, valuePtr unsafe.Pointer) bool
CFDictionaryCreateFunc func(allocator uintptr, keys, values *unsafe.Pointer, numValues int64,
keyCallBacks, valueCallBacks uintptr) unsafe.Pointer
CFDictionaryAddValueFunc func(theDict, key, value uintptr)
@@ -413,13 +472,16 @@ type MachTimeBaseInfo struct {
Denom uint32
}
+// Buffers the kernel writes into are declared as unsafe.Pointer; see the note
+// above the IOKit function types. vmAddress on VMDeallocateFunc stays a uintptr
+// because it names kernel-allocated memory rather than Go memory.
type (
- HostProcessorInfoFunc func(host uint32, flavor int32, outProcessorCount *uint32, outProcessorInfo uintptr,
+ HostProcessorInfoFunc func(host uint32, flavor int32, outProcessorCount *uint32, outProcessorInfo unsafe.Pointer,
outProcessorInfoCnt *uint32) int32
- HostStatisticsFunc func(host uint32, flavor int32, hostInfoOut uintptr, hostInfoOutCnt *uint32) int32
+ HostStatisticsFunc func(host uint32, flavor int32, hostInfoOut unsafe.Pointer, hostInfoOutCnt *uint32) int32
MachHostSelfFunc func() uint32
MachTaskSelfFunc func() uint32
- MachTimeBaseInfoFunc func(info uintptr) int32
+ MachTimeBaseInfoFunc func(info unsafe.Pointer) int32
VMDeallocateFunc func(targetTask uint32, vmAddress, vmSize uintptr) int32
)
@@ -440,14 +502,18 @@ const (
)
type (
- ProcPidPathFunc func(pid int32, buffer uintptr, bufferSize uint32) int32
- ProcPidInfoFunc func(pid, flavor int32, arg uint64, buffer uintptr, bufferSize int32) int32
+ ProcPidPathFunc func(pid int32, buffer unsafe.Pointer, bufferSize uint32) int32
+ ProcPidInfoFunc func(pid, flavor int32, arg uint64, buffer unsafe.Pointer, bufferSize int32) int32
+ ProcPidRusageFunc func(pid, flavor int32, buffer unsafe.Pointer) int32
+ ErrnoFunc func() *int32
)
const (
- SysctlSym = "sysctl"
- ProcPidPathSym = "proc_pidpath"
- ProcPidInfoSym = "proc_pidinfo"
+ SysctlSym = "sysctl"
+ ProcPidPathSym = "proc_pidpath"
+ ProcPidInfoSym = "proc_pidinfo"
+ ProcPidRusageSym = "proc_pid_rusage"
+ ErrnoSym = "__error"
)
const (
@@ -456,6 +522,10 @@ const (
PROC_PIDPATHINFO_MAXSIZE = 4 * MAXPATHLEN
PROC_PIDTASKINFO = 4
PROC_PIDVNODEPATHINFO = 9
+
+ // RUSAGE_INFO_V2 is the proc_pid_rusage flavor that includes disk I/O bytes.
+ // See sys/resource.h rusage_info_v2.
+ RUSAGE_INFO_V2 = 2
)
// SMC represents a SMC instance.
@@ -507,15 +577,18 @@ func NewSMC() (*SMC, error) {
}, nil
}
-func (s *SMC) CallStruct(selector uint32, inputStruct, inputStructCnt, outputStruct uintptr, outputStructCnt *uintptr) int32 {
+func (s *SMC) CallStruct(selector uint32, inputStruct unsafe.Pointer, inputStructCnt uintptr,
+ outputStruct unsafe.Pointer, outputStructCnt *uintptr,
+) int32 {
return s.lib.IOConnectCallStructMethod(s.conn, selector, inputStruct, inputStructCnt, outputStruct, outputStructCnt)
}
+// Close releases the SMC connection. The IOKit handle itself is shared
+// process-wide and is deliberately left open; see newLibrary.
func (s *SMC) Close() error {
if result := s.lib.IOServiceClose(s.conn); result != 0 {
return errors.New("ERROR: IOServiceClose failed")
}
- s.lib.Close()
return nil
}
@@ -537,10 +610,6 @@ func (s CStr) Ptr() *byte {
return &s[0]
}
-func (s CStr) Addr() uintptr {
- return uintptr(unsafe.Pointer(s.Ptr()))
-}
-
func (s CStr) GoString() string {
if s == nil {
return ""
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_darwin.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_darwin.go
index 1b3e9f21..58746a61 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_darwin.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_darwin.go
@@ -95,7 +95,7 @@ func VirtualMemoryWithContext(_ context.Context) (*VirtualMemoryStat, error) {
var vmstat vmStatisticsData
status := sys.HostStatistics(sys.MachHostSelf(), common.HOST_VM_INFO,
- uintptr(unsafe.Pointer(&vmstat)), &count)
+ unsafe.Pointer(&vmstat), &count)
if status != common.KERN_SUCCESS {
return nil, fmt.Errorf("host_statistics error=%d", status)
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_linux.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_linux.go
index a888c5ba..a33cd03b 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_linux.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_linux.go
@@ -479,7 +479,7 @@ func parseSwapsFile(ctx context.Context, r io.Reader) ([]*SwapDevice, error) {
// Check header headerFields are as expected
headerFields := strings.Fields(scanner.Text())
- if len(headerFields) < usedCol {
+ if len(headerFields) <= usedCol {
return nil, fmt.Errorf("couldn't parse %q: too few fields in header", swapsFilePath)
}
if headerFields[nameCol] != "Filename" {
@@ -495,7 +495,7 @@ func parseSwapsFile(ctx context.Context, r io.Reader) ([]*SwapDevice, error) {
var swapDevices []*SwapDevice
for scanner.Scan() {
fields := strings.Fields(scanner.Text())
- if len(fields) < usedCol {
+ if len(fields) <= usedCol {
return nil, fmt.Errorf("couldn't parse %q: too few fields", swapsFilePath)
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_linux.go b/vendor/github.com/shirou/gopsutil/v4/net/net_linux.go
index 96a78ff8..06c98d1f 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_linux.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_linux.go
@@ -50,6 +50,10 @@ func IOCountersByFileWithContext(_ context.Context, pernic bool, filename string
return nil, err
}
+ if len(lines) < 2 {
+ return nil, fmt.Errorf("malformed %s: expected at least 2 header lines, got %d", filename, len(lines))
+ }
+
statlen := len(lines) - 1
ret := make([]IOCountersStat, 0, statlen)
@@ -764,7 +768,7 @@ func processUnix(file string, kind netConnectionKindType, inodes map[string][]in
// skip first line
for _, line := range lines[1:] {
tokens := strings.Fields(string(line))
- if len(tokens) < 6 {
+ if len(tokens) < 7 {
continue
}
st, err := strconv.ParseInt(tokens[4], 10, 32)
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_windows.go b/vendor/github.com/shirou/gopsutil/v4/net/net_windows.go
index f530e4e5..22dae714 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_windows.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_windows.go
@@ -365,7 +365,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
return nil, errors.New("faimly must be required")
}
- for {
+ for retry := 0; retry < 10; retry++ {
switch family {
case kindTCP4.family:
if len(buf) > 0 {
@@ -395,6 +395,12 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
+ if retry == 9 {
+ return nil, errors.New("GetExtendedTcpTable: failed to allocate sufficient buffer after 10 retries")
+ }
+
+ // Add 4KB padding to account for concurrent connection growth between calls.
+ size += 4096
buf = make([]byte, size)
}
@@ -446,7 +452,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
return nil, errors.New("faimly must be required")
}
- for {
+ for retry := 0; retry < 10; retry++ {
switch family {
case kindUDP4.family:
if len(buf) > 0 {
@@ -478,6 +484,12 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
+ if retry == 9 {
+ return nil, errors.New("GetExtendedUdpTable: failed to allocate sufficient buffer after 10 retries")
+ }
+
+ // Add 4KB padding to account for concurrent connection growth between calls.
+ size += 4096
buf = make([]byte, size)
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process.go b/vendor/github.com/shirou/gopsutil/v4/process/process.go
index 5db5ff48..63b07e51 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process.go
@@ -110,12 +110,14 @@ type IOCountersStat struct {
// WriteCount is a number of read I/O operations such as syscalls.
WriteCount uint64 `json:"writeCount"`
// ReadBytes is a number of all I/O read in bytes. This includes disk I/O on Linux and Windows.
+ // Darwin does not expose this and reports 0; use DiskReadBytes there.
ReadBytes uint64 `json:"readBytes"`
- // WriteBytes is a number of all I/O write in bytes. This includes disk I/O on Linux and Windows.
+ // WriteBytes is a number of all I/O written in bytes. This includes disk I/O on Linux and Windows.
+ // Darwin does not expose this and reports 0; use DiskWriteBytes there.
WriteBytes uint64 `json:"writeBytes"`
- // DiskReadBytes is a number of disk I/O write in bytes. Currently only Linux has this value.
+ // DiskReadBytes is a number of disk I/O read in bytes. Currently, Linux and Darwin have this value.
DiskReadBytes uint64 `json:"diskReadBytes"`
- // DiskWriteBytes is a number of disk I/O read in bytes. Currently only Linux has this value.
+ // DiskWriteBytes is a number of disk I/O written in bytes. Currently, Linux and Darwin have this value.
DiskWriteBytes uint64 `json:"diskWriteBytes"`
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go b/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go
index 6e1d0ce3..6bb88d7e 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go
@@ -7,7 +7,6 @@ import (
"bytes"
"context"
"encoding/binary"
- "errors"
"fmt"
"path/filepath"
"runtime"
@@ -179,8 +178,72 @@ func (p *Process) NiceWithContext(_ context.Context) (int32, error) {
return int32(k.Proc.P_nice), nil
}
-func (*Process) IOCountersWithContext(_ context.Context) (*IOCountersStat, error) {
- return nil, common.ErrNotImplementedError
+// rusageInfoV2 mirrors Darwin's struct rusage_info_v2 from sys/resource.h.
+// Only DiskIOBytesRead / DiskIOBytesWritten are used for IOCounters.
+type rusageInfoV2 struct {
+ UUID [16]byte
+ UserTime uint64
+ SystemTime uint64
+ PkgIdleWkups uint64
+ InterruptWkups uint64
+ Pageins uint64
+ WiredSize uint64
+ ResidentSize uint64
+ PhysFootprint uint64
+ ProcStartAbstime uint64
+ ProcExitAbstime uint64
+ ChildUserTime uint64
+ ChildSystemTime uint64
+ ChildPkgIdleWkups uint64
+ ChildInterruptWkups uint64
+ ChildPageins uint64
+ ChildElapsedAbstime uint64
+ DiskIOBytesRead uint64
+ DiskIOBytesWritten uint64
+}
+
+// IOCountersWithContext returns cumulative disk I/O bytes for the process via
+// proc_pid_rusage(RUSAGE_INFO_V2).
+//
+// Darwin only reports disk I/O, so only DiskReadBytes and DiskWriteBytes are
+// populated. ReadBytes/WriteBytes count all I/O including that served from
+// cache on other platforms, which has no Darwin equivalent, and ReadCount /
+// WriteCount are not exposed at all; all four stay zero.
+//
+// Access may fail with ErrorNotPermitted for protected processes.
+func (p *Process) IOCountersWithContext(_ context.Context) (*IOCountersStat, error) {
+ funcs, err := loadProcFuncs()
+ if err != nil {
+ return nil, err
+ }
+ defer funcs.Close()
+
+ // Lock the OS thread so that errno, which is thread-local, still belongs to
+ // the thread that made the call below by the time it is read.
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ // Resolve the errno location up front: doing it after the call would run a
+ // dlsym and allocate in between, either of which can overwrite errno.
+ errnoPtr := funcs.lib.ErrnoLocation()
+
+ var usage rusageInfoV2
+ ret := funcs.lib.ProcPidRusage(p.Pid, common.RUSAGE_INFO_V2, unsafe.Pointer(&usage))
+ if ret != 0 {
+ switch errno := unix.Errno(*errnoPtr); errno {
+ case unix.EPERM:
+ return nil, ErrorNotPermitted
+ case unix.ESRCH:
+ return nil, ErrorProcessNotRunning
+ default:
+ return nil, fmt.Errorf("proc_pid_rusage failed for pid %d: %w", p.Pid, errno)
+ }
+ }
+
+ return &IOCountersStat{
+ DiskReadBytes: usage.DiskIOBytesRead,
+ DiskWriteBytes: usage.DiskIOBytesWritten,
+ }, nil
}
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
@@ -294,7 +357,7 @@ func loadProcFuncs() (*dlFuncs, error) {
func (f *dlFuncs) getTimeScaleToNanoSeconds() float64 {
var timeBaseInfo common.MachTimeBaseInfo
- f.lib.MachTimeBaseInfo(uintptr(unsafe.Pointer(&timeBaseInfo)))
+ f.lib.MachTimeBaseInfo(unsafe.Pointer(&timeBaseInfo))
return float64(timeBaseInfo.Numer) / float64(timeBaseInfo.Denom)
}
@@ -311,7 +374,7 @@ func (p *Process) ExeWithContext(_ context.Context) (string, error) {
defer funcs.Close()
buf := common.NewCStr(common.PROC_PIDPATHINFO_MAXSIZE)
- ret := funcs.lib.ProcPidPath(p.Pid, buf.Addr(), common.PROC_PIDPATHINFO_MAXSIZE)
+ ret := funcs.lib.ProcPidPath(p.Pid, unsafe.Pointer(buf.Ptr()), common.PROC_PIDPATHINFO_MAXSIZE)
if ret <= 0 {
return "", fmt.Errorf("unknown error: proc_pidpath returned %d", ret)
@@ -332,20 +395,24 @@ func (p *Process) CwdWithContext(_ context.Context) (string, error) {
}
defer funcs.Close()
- // Lock OS thread to ensure the errno does not change
+ // Lock the OS thread so that errno, which is thread-local, still belongs to
+ // the thread that made the call below by the time it is read.
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ // Resolve the errno location up front: doing it after the call would run a
+ // dlsym and allocate in between, either of which can overwrite errno.
+ errnoPtr := funcs.lib.ErrnoLocation()
+
var vpi vnodePathInfo
const vpiSize = int32(unsafe.Sizeof(vpi))
- ret := funcs.lib.ProcPidInfo(p.Pid, common.PROC_PIDVNODEPATHINFO, 0, uintptr(unsafe.Pointer(&vpi)), vpiSize)
- errno, _ := funcs.lib.Dlsym("errno")
- err = *(**unix.Errno)(unsafe.Pointer(&errno))
- if errors.Is(err, unix.EPERM) {
- return "", ErrorNotPermitted
- }
-
+ ret := funcs.lib.ProcPidInfo(p.Pid, common.PROC_PIDVNODEPATHINFO, 0, unsafe.Pointer(&vpi), vpiSize)
if ret <= 0 {
+ // errno is only meaningful once the call has reported failure; reading it
+ // unconditionally can surface a stale value from an earlier call.
+ if errno := unix.Errno(*errnoPtr); errno == unix.EPERM {
+ return "", ErrorNotPermitted
+ }
return "", fmt.Errorf("unknown error: proc_pidinfo returned %d", ret)
}
@@ -450,7 +517,7 @@ func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) {
defer funcs.Close()
var ti ProcTaskInfo
- funcs.lib.ProcPidInfo(p.Pid, common.PROC_PIDTASKINFO, 0, uintptr(unsafe.Pointer(&ti)), int32(unsafe.Sizeof(ti)))
+ funcs.lib.ProcPidInfo(p.Pid, common.PROC_PIDTASKINFO, 0, unsafe.Pointer(&ti), int32(unsafe.Sizeof(ti)))
return int32(ti.Threadnum), nil
}
@@ -463,7 +530,7 @@ func (p *Process) TimesWithContext(_ context.Context) (*cpu.TimesStat, error) {
defer funcs.Close()
var ti ProcTaskInfo
- funcs.lib.ProcPidInfo(p.Pid, common.PROC_PIDTASKINFO, 0, uintptr(unsafe.Pointer(&ti)), int32(unsafe.Sizeof(ti)))
+ funcs.lib.ProcPidInfo(p.Pid, common.PROC_PIDTASKINFO, 0, unsafe.Pointer(&ti), int32(unsafe.Sizeof(ti)))
timescaleToNanoSeconds := funcs.getTimeScaleToNanoSeconds()
ret := &cpu.TimesStat{
@@ -482,7 +549,7 @@ func (p *Process) MemoryInfoWithContext(_ context.Context) (*MemoryInfoStat, err
defer funcs.Close()
var ti ProcTaskInfo
- funcs.lib.ProcPidInfo(p.Pid, common.PROC_PIDTASKINFO, 0, uintptr(unsafe.Pointer(&ti)), int32(unsafe.Sizeof(ti)))
+ funcs.lib.ProcPidInfo(p.Pid, common.PROC_PIDTASKINFO, 0, unsafe.Pointer(&ti), int32(unsafe.Sizeof(ti)))
ret := &MemoryInfoStat{
RSS: uint64(ti.Resident_size),
@@ -513,8 +580,8 @@ func (p *Process) NumFDsWithContext(_ context.Context) (int32, error) {
p.Pid,
common.PROC_PIDLISTFDS,
0,
- 0, // NULL buffer
- 0, // 0 size
+ nil, // NULL buffer
+ 0, // 0 size
)
if bufferSize <= 0 {
return 0, fmt.Errorf("unknown error: proc_pidinfo returned %d", bufferSize)
@@ -530,8 +597,8 @@ func (p *Process) NumFDsWithContext(_ context.Context) (int32, error) {
p.Pid,
common.PROC_PIDLISTFDS,
0,
- uintptr(unsafe.Pointer(&buf[0])), // Real buffer
- bufferSize, // Size from first call
+ unsafe.Pointer(&buf[0]), // Real buffer
+ bufferSize, // Size from first call
)
if ret <= 0 {
return 0, fmt.Errorf("unknown error: proc_pidinfo returned %d", ret)
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_linux.go b/vendor/github.com/shirou/gopsutil/v4/process/process_linux.go
index dc2f03bb..36d95d10 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_linux.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_linux.go
@@ -350,6 +350,9 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
continue
}
fields := splitProcStat(statContents)
+ if len(fields) < 5 {
+ continue
+ }
pid, err := strconv.ParseInt(fields[1], 10, 32)
if err != nil {
continue
@@ -756,6 +759,9 @@ func (p *Process) fillFromStatmWithContext(ctx context.Context) (*MemoryInfoStat
return nil, nil, err
}
fields := strings.Split(string(contents), " ")
+ if len(fields) < 6 {
+ return nil, nil, fmt.Errorf("malformed statm file: expected at least 6 fields, got %d", len(fields))
+ }
vms, err := strconv.ParseUint(fields[0], 10, 64)
if err != nil {
@@ -861,6 +867,12 @@ func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
// Ensure we have a copy and not reference into slice
p.name = string([]byte(p.name))
case "State":
+ if value == "" {
+ // Clear rather than leave a stale status from a previous
+ // parse, since Process objects can be reused across calls.
+ p.status = ""
+ continue
+ }
p.status = convertStatusChar(value[0:1])
// Ensure we have a copy and not reference into slice
p.status = string([]byte(p.status))
@@ -1195,6 +1207,12 @@ func readPidsFromDir(path string) ([]int32, error) {
func splitProcStat(content []byte) []string {
nameStart := bytes.IndexByte(content, '(')
nameEnd := bytes.LastIndexByte(content, ')')
+ // Guard against a malformed/truncated stat file that is missing the
+ // parentheses around comm, which would otherwise cause the slice
+ // operations below to panic. Callers validate the field count.
+ if nameStart < 0 || nameEnd < nameStart || nameEnd+2 > len(content) {
+ return nil
+ }
restFields := strings.Fields(string(content[nameEnd+2:])) // +2 skip ') '
name := content[nameStart+1 : nameEnd]
pid := strings.TrimSpace(string(content[:nameStart]))
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_openbsd.go b/vendor/github.com/shirou/gopsutil/v4/process/process_openbsd.go
index 31fdb85b..07257a85 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_openbsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_openbsd.go
@@ -8,6 +8,7 @@ import (
"context"
"encoding/binary"
"errors"
+ "fmt"
"io"
"path/filepath"
"sort"
@@ -94,6 +95,9 @@ func (p *Process) CmdlineSliceWithContext(_ context.Context) ([]string, error) {
pointers followed by the strings themselves. The last char
pointer is a NULL pointer. */
var strParts []string
+ if len(buf) == 0 {
+ return strParts, nil
+ }
r := bytes.NewReader(buf)
baseAddr := uintptr(unsafe.Pointer(&buf[0]))
for {
@@ -105,7 +109,17 @@ func (p *Process) CmdlineSliceWithContext(_ context.Context) ([]string, error) {
break
}
offset := argvp - baseAddr
- length := uintptr(bytes.IndexByte(buf[offset:], 0))
+ // Reject a malformed/truncated sysctl reply whose pointers fall
+ // outside buf or whose strings are not NUL-terminated, which would
+ // otherwise cause the slice operations below to panic.
+ if offset >= uintptr(len(buf)) {
+ return nil, fmt.Errorf("malformed KERN_PROC_ARGV reply for pid %d: argv pointer out of bounds", p.Pid)
+ }
+ idx := bytes.IndexByte(buf[offset:], 0)
+ if idx < 0 {
+ return nil, fmt.Errorf("malformed KERN_PROC_ARGV reply for pid %d: argv string not NUL-terminated", p.Pid)
+ }
+ length := uintptr(idx)
str := string(buf[offset : offset+length])
strParts = append(strParts, str)
}
diff --git a/vendor/github.com/sirupsen/logrus/.golangci.yml b/vendor/github.com/sirupsen/logrus/.golangci.yml
index 792db361..c9a840e0 100644
--- a/vendor/github.com/sirupsen/logrus/.golangci.yml
+++ b/vendor/github.com/sirupsen/logrus/.golangci.yml
@@ -1,12 +1,9 @@
version: "2"
-run:
- tests: false
linters:
enable:
- asasalint
- asciicheck
- bidichk
- - bodyclose
- contextcheck
- durationcheck
- errchkjson
@@ -22,46 +19,21 @@ linters:
- nilerr
- nilnesserr
- noctx
- - protogetter
- reassign
- recvcheck
- - rowserrcheck
- - spancheck
- - sqlclosecheck
- testifylint
- unparam
- - zerologlint
- disable:
- - prealloc
- settings:
- errcheck:
- check-type-assertions: false
- check-blank: false
- lll:
- line-length: 100
- tab-width: 4
- prealloc:
- simple: false
- range-loops: false
- for-loops: false
- whitespace:
- multi-if: false
- multi-func: false
exclusions:
- generated: lax
presets:
- - comments
- - common-false-positives
- legacy
- std-error-handling
- paths:
- - third_party$
- - builtin$
- - examples$
-formatters:
- exclusions:
- generated: lax
- paths:
- - third_party$
- - builtin$
- - examples$
+ rules:
+ # Exclude some linters from running on tests files.
+ - path: _test\.go
+ linters:
+ - gosec
+ - musttag
+ - noctx # TODO: enable once we switch to Go 1.24+.
+ - linters: # TODO: remove once golangci-lint is updated with https://github.com/golangci/golangci-lint/pull/6584
+ - gocheckcompilerdirectives
+ text: 'compiler directive unrecognized: //go:fix'
diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml
deleted file mode 100644
index c1dbd5a3..00000000
--- a/vendor/github.com/sirupsen/logrus/.travis.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-language: go
-go_import_path: github.com/sirupsen/logrus
-git:
- depth: 1
-env:
- - GO111MODULE=on
-go: 1.15.x
-os: linux
-install:
- - ./travis/install.sh
-script:
- - cd ci
- - go run mage.go -v -w ../ crossBuild
- - go run mage.go -v -w ../ lint
- - go run mage.go -v -w ../ test
diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md
index 098608ff..3e667563 100644
--- a/vendor/github.com/sirupsen/logrus/CHANGELOG.md
+++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md
@@ -1,90 +1,246 @@
-# 1.8.1
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+## 1.10.1
+
+Fixes:
+
+ * Fix a regression introduced in v1.10.0 where `TextFormatter` could panic
+ when formatting nil or panicking `error` and `fmt.Stringer` values.
+ * Allow function-backed implementations of `error` as field values.
+
+## 1.10.0
+
+Fixes:
+
+ * Fix reentrant logging deadlocks in formatter paths.
+ * Fix race conditions in formatter and entry handling.
+ * Fix generic `Log`, `Logf`, `Logln`, and `LogFn` methods unexpectedly
+ panicking when called with `PanicLevel`. Use the corresponding `Panic`
+ methods when panic behavior is desired.
+ * Improve concurrency safety around formatter and hook access.
+
+Features:
+
+ * Add `slog` hook for forwarding Logrus entries to `log/slog`.
+ * Add `slog.Handler` for forwarding `log/slog` records to a Logrus logger,
+ including levels, fields, groups, context, time, and optional caller
+ reporting. The hook and handler can also be combined to help migrate
+ between Logrus and `log/slog`.
+ * Add minimal, composable logging interfaces for each log level. This enables
+ consumers to depend on narrower interfaces, making it easier to substitute
+ or adapt logging implementations.
+ * Allow `Entry.Caller` to be set explicitly and preserve it across derived
+ entries, enabling custom caller detection without Logrus overwriting
+ caller information when `ReportCaller` is enabled.
+
+Changed:
+
+ * Raise minimum supported Go version to 1.23.
+ * TextFormatter now renders `[]byte` values as raw/quoted strings instead of slice-of-ints.
+ * TextFormatter now uses distinct dimmed colors for debug and trace output.
+ * TextFormatter now automatically enables colors on Windows terminals with ANSI support,
+ matching the behavior on other platforms.
+ * `Entry.HasCaller` is now deprecated in favor of checking `Entry.Caller` directly.
+ * Deprecated `MutexWrap`, which was unintentionally exposed as public API.
+ It remains available as an alias for compatibility but should not be used
+ directly.
+
+Performance:
+
+ * Significantly improve TextFormatter performance and reduce allocations.
+ * Optimize common Entry and Logger hot paths.
+ * Reduce allocations in caller reporting.
+ * ~17% lower geomean runtime and ~27% higher formatter throughput overall.
+ * Common enabled logging paths are ~30–44% faster.
+ * TextFormatter paths are up to ~40% faster, with allocation counts reduced
+ by 25–74% across the measured formatter cases.
+
+
+## 1.9.4
+
+Fixes:
+
+ * Remove uses of deprecated `ioutil` package
+
+Features:
+
+ * Add GNU/Hurd support
+ * Add WASI wasip1 support
+
+Code quality:
+
+ * Update minimum supported Go version to 1.17
+ * Documentation updates
+
+
+## 1.9.3
+
+Fixes:
+
+ * Re-apply fix for potential denial of service in logrus.Writer() when logging >64KB single-line payloads without newlines (#1376)
+ * Fix panic in Writer
+
+
+## 1.9.2
+
+Fixes:
+
+ * Revert Writer DoS fix (#1376) due to regression
+
+
+## 1.9.1
+
+Fixes:
+
+ * Fix potential denial of service in logrus.Writer() when logging >64KB single-line payloads without newlines (#1376)
+
+
+## 1.9.0
+
+Fixes:
+
+ * Multiple concurrency and race condition fixes
+ * Improve Windows terminal and ANSI handling
+
+Code quality:
+
+ * Internal cleanups and modernization
+
+
+## 1.8.3
+
+Fixes:
+
+ * Fix potential denial of service in logrus.Writer() when logging >64KB single-line payloads without newlines (#1376)
+
+
+## 1.8.2
+
+Features:
+
+ * Add support for the logger private buffer pool (#1253)
+
+Fixes:
+
+ * Fix race condition for SetFormatter and SetReportCaller
+ * Fix data race in hooks test package
+
+## 1.8.1
+
Code quality:
+
* move magefile in its own subdir/submodule to remove magefile dependency on logrus consumer
* improve timestamp format documentation
Fixes:
+
* fix race condition on logger hooks
-# 1.8.0
+## 1.8.0
Correct versioning number replacing v1.7.1.
-# 1.7.1
+## 1.7.1
Beware this release has introduced a new public API and its semver is therefore incorrect.
Code quality:
+
* use go 1.15 in travis
* use magefile as task runner
Fixes:
+
* small fixes about new go 1.13 error formatting system
* Fix for long time race condiction with mutating data hooks
Features:
+
* build support for zos
-# 1.7.0
+## 1.7.0
+
Fixes:
+
* the dependency toward a windows terminal library has been removed
Features:
+
* a new buffer pool management API has been added
* a set of `Fn()` functions have been added
-# 1.6.0
+## 1.6.0
+
Fixes:
+
* end of line cleanup
* revert the entry concurrency bug fix which leads to deadlock under some circumstances
* update dependency on go-windows-terminal-sequences to fix a crash with go 1.14
Features:
+
* add an option to the `TextFormatter` to completely disable fields quoting
-# 1.5.0
+## 1.5.0
+
Code quality:
+
* add golangci linter run on travis
Fixes:
+
* add mutex for hooks concurrent access on `Entry` data
* caller function field for go1.14
* fix build issue for gopherjs target
Feature:
+
* add an hooks/writer sub-package whose goal is to split output on different stream depending on the trace level
* add a `DisableHTMLEscape` option in the `JSONFormatter`
* add `ForceQuote` and `PadLevelText` options in the `TextFormatter`
-# 1.4.2
+## 1.4.2
+
* Fixes build break for plan9, nacl, solaris
-# 1.4.1
+
+## 1.4.1
+
This new release introduces:
+
* Enhance TextFormatter to not print caller information when they are empty (#944)
* Remove dependency on golang.org/x/crypto (#932, #943)
Fixes:
+
* Fix Entry.WithContext method to return a copy of the initial entry (#941)
-# 1.4.0
+## 1.4.0
+
This new release introduces:
+
* Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848).
* Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter` (#909, #911)
* Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919).
Fixes:
+
* Fix wrong method calls `Logger.Print` and `Logger.Warningln` (#893).
* Update `Entry.Logf` to not do string formatting unless the log level is enabled (#903)
* Fix infinite recursion on unknown `Level.String()` (#907)
* Fix race condition in `getCaller` (#916).
-# 1.3.0
+## 1.3.0
+
This new release introduces:
+
* Log, Logf, Logln functions for Logger and Entry that take a Level
Fixes:
+
* Building prometheus node_exporter on AIX (#840)
* Race condition in TextFormatter (#468)
* Travis CI import path (#868)
@@ -92,20 +248,26 @@ Fixes:
* Pointer to func as field in JSONFormatter (#870)
* Properly marshal Levels (#873)
-# 1.2.0
+## 1.2.0
+
This new release introduces:
+
* A new method `SetReportCaller` in the `Logger` to enable the file, line and calling function from which the trace has been issued
* A new trace level named `Trace` whose level is below `Debug`
* A configurable exit function to be called upon a Fatal trace
* The `Level` object now implements `encoding.TextUnmarshaler` interface
-# 1.1.1
+## 1.1.1
+
This is a bug fix release.
+
* fix the build break on Solaris
* don't drop a whole trace in JSONFormatter when a field param is a function pointer which can not be serialized
-# 1.1.0
+## 1.1.0
+
This new release introduces:
+
* several fixes:
* a fix for a race condition on entry formatting
* proper cleanup of previously used entries before putting them back in the pool
@@ -122,9 +284,10 @@ This new release introduces:
* the field sort function is now configurable for text formatter
* the CLICOLOR and CLICOLOR\_FORCE environment variable support in text formater
-# 1.0.6
+## 1.0.6
This new release introduces:
+
* a new api WithTime which allows to easily force the time of the log entry
which is mostly useful for logger wrapper
* a fix reverting the immutability of the entry given as parameter to the hooks
@@ -134,71 +297,71 @@ This new release introduces:
* a new configuration of the textformatter to configure the name of the default keys
* a new configuration of the text formatter to disable the level truncation
-# 1.0.5
+## 1.0.5
* Fix hooks race (#707)
* Fix panic deadlock (#695)
-# 1.0.4
+## 1.0.4
* Fix race when adding hooks (#612)
* Fix terminal check in AppEngine (#635)
-# 1.0.3
+## 1.0.3
* Replace example files with testable examples
-# 1.0.2
+## 1.0.2
* bug: quote non-string values in text formatter (#583)
* Make (*Logger) SetLevel a public method
-# 1.0.1
+## 1.0.1
* bug: fix escaping in text formatter (#575)
-# 1.0.0
+## 1.0.0
* Officially changed name to lower-case
* bug: colors on Windows 10 (#541)
* bug: fix race in accessing level (#512)
-# 0.11.5
+## 0.11.5
* feature: add writer and writerlevel to entry (#372)
-# 0.11.4
+## 0.11.4
* bug: fix undefined variable on solaris (#493)
-# 0.11.3
+## 0.11.3
* formatter: configure quoting of empty values (#484)
* formatter: configure quoting character (default is `"`) (#484)
* bug: fix not importing io correctly in non-linux environments (#481)
-# 0.11.2
+## 0.11.2
* bug: fix windows terminal detection (#476)
-# 0.11.1
+## 0.11.1
* bug: fix tty detection with custom out (#471)
-# 0.11.0
+## 0.11.0
* performance: Use bufferpool to allocate (#370)
* terminal: terminal detection for app-engine (#343)
* feature: exit handler (#375)
-# 0.10.0
+## 0.10.0
* feature: Add a test hook (#180)
* feature: `ParseLevel` is now case-insensitive (#326)
* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308)
* performance: avoid re-allocations on `WithFields` (#335)
-# 0.9.0
+## 0.9.0
* logrus/text_formatter: don't emit empty msg
* logrus/hooks/airbrake: move out of main repository
@@ -210,25 +373,25 @@ This new release introduces:
* logrus/core: support `WithError` on logger
* logrus/core: Solaris support
-# 0.8.7
+## 0.8.7
* logrus/core: fix possible race (#216)
* logrus/doc: small typo fixes and doc improvements
-# 0.8.6
+## 0.8.6
* hooks/raven: allow passing an initialized client
-# 0.8.5
+## 0.8.5
* logrus/core: revert #208
-# 0.8.4
+## 0.8.4
* formatter/text: fix data race (#218)
-# 0.8.3
+## 0.8.3
* logrus/core: fix entry log level (#208)
* logrus/core: improve performance of text formatter by 40%
@@ -236,24 +399,24 @@ This new release introduces:
* logrus/core: add support for DragonflyBSD and NetBSD
* formatter/text: print structs more verbosely
-# 0.8.2
+## 0.8.2
* logrus: fix more Fatal family functions
-# 0.8.1
+## 0.8.1
* logrus: fix not exiting on `Fatalf` and `Fatalln`
-# 0.8.0
+## 0.8.0
* logrus: defaults to stderr instead of stdout
* hooks/sentry: add special field for `*http.Request`
* formatter/text: ignore Windows for colors
-# 0.7.3
+## 0.7.3
* formatter/\*: allow configuration of timestamp layout
-# 0.7.2
+## 0.7.2
* formatter/text: Add configuration option for time format (#158)
diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md
index cc5dab7e..b2ff7aff 100644
--- a/vendor/github.com/sirupsen/logrus/README.md
+++ b/vendor/github.com/sirupsen/logrus/README.md
@@ -3,13 +3,10 @@
Logrus is a structured logger for Go (golang), completely API compatible with
the standard library logger.
-**Logrus is in maintenance-mode.** We will not be introducing new features. It's
-simply too hard to do in a way that won't break many people's projects, which is
-the last thing you want from your Logging library (again...).
-
-This does not mean Logrus is dead. Logrus will continue to be maintained for
-security, (backwards compatible) bug fixes, and performance (where we are
-limited by the interface).
+**Logrus is in maintenance mode.** The project focuses on security, bug fixes,
+and performance improvements. New features are not planned, aside from changes
+required to provide interoperability with other logging ecosystems (e.g., Go's
+[log/slog](https://pkg.go.dev/log/slog)).
I believe Logrus' biggest contribution is to have played a part in today's
widespread use of structured logging in Golang. There doesn't seem to be a
@@ -23,18 +20,6 @@ about structured logging in Go today. Check out, for example,
[zap]: https://github.com/uber-go/zap
[apex]: https://github.com/apex/log
-**Seeing weird case-sensitive problems?** It's in the past been possible to
-import Logrus as both upper- and lower-case. Due to the Go package environment,
-this caused issues in the community and we needed a standard. Some environments
-experienced problems with the upper-case variant, so the lower-case was decided.
-Everything using `logrus` will need to use the lower-case:
-`github.com/sirupsen/logrus`. Any package that isn't, should be changed.
-
-To fix Glide, see [these
-comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437).
-For an in-depth explanation of the casing issue, see [this
-comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276).
-
Nicely color-coded in development (when a TTY is attached, otherwise just
plain text):
@@ -43,35 +28,27 @@ plain text):
With `logrus.SetFormatter(&logrus.JSONFormatter{})`, for easy parsing by logstash
or Splunk:
-```text
-{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
-ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
-
-{"level":"warning","msg":"The group's number increased tremendously!",
-"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
-
-{"animal":"walrus","level":"info","msg":"A giant walrus appears!",
-"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
-
-{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
-"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
-
-{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
-"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
+```json lines
+{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
+{"level":"warning","msg":"The group's number increased tremendously!","number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
+{"animal":"walrus","level":"info","msg":"A giant walrus appears!","size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
+{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.","size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
+{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
```
With the default `logrus.SetFormatter(&logrus.TextFormatter{})` when a TTY is not
attached, the output is compatible with the
[logfmt](https://pkg.go.dev/github.com/kr/logfmt) format:
-```text
+```bash
time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
-time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true
+time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" animal=orca err="It's over 9000!" number=100 omg=true size=9009
```
+
To ensure this behaviour even if a TTY is attached, set your formatter as follows:
```go
@@ -88,29 +65,32 @@ If you wish to add the calling method as a field, instruct the logger via:
```go
logrus.SetReportCaller(true)
```
+
This adds the caller as 'method' like so:
```json
-{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by",
-"time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
+{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by","time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
```
-```text
+```bash
time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin
```
+
Note that this does add measurable overhead - the cost will depend on the version of Go, but is
between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your
environment via benchmarks:
```bash
-go test -bench=.*CallerTracing
+go test -bench=ReportCaller
```
#### Case-sensitivity
-The organization's name was changed to lower-case--and this will not be changed
-back. If you are getting import conflicts due to case sensitivity, please use
-the lower-case import: `github.com/sirupsen/logrus`.
+The organization's name was [changed to lower-case][1]. If you are getting import
+conflicts due to case sensitivity, please use the lower-case import:
+`github.com/sirupsen/logrus`.
+
+[1]: https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276
#### Example
@@ -289,6 +269,7 @@ func init() {
}
}
```
+
Note: Syslog hooks also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
A list of currently known service hooks can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks)
@@ -367,18 +348,21 @@ Splunk or Logstash.
The built-in logging formatters are:
-* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise
- without colors.
- * *Note:* to force colored output when there is no TTY, set the `ForceColors`
+* [`logrus.TextFormatter`](https://pkg.go.dev/github.com/sirupsen/logrus#TextFormatter)
+ logs the event in colors if the logger output is a TTY, otherwise without colors.
+ * To force colored output when there is no TTY, set the `ForceColors`
field to `true`. To force no colored output even if there is a TTY set the
- `DisableColors` field to `true`. For Windows, see
- [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
+ `DisableColors` field to `true`.
+ * On modern Windows terminals with ANSI (Virtual Terminal) support, TextFormatter
+ automatically enables colored output.
+ * If your environment does not support ANSI escape sequences, wrap the logger output
+ using [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable)
+ and set `ForceColors` (or `CLICOLOR_FORCE=1`) to enable colors through the wrapper.
* When colors are enabled, levels are truncated to 4 characters by default. To disable
truncation set the `DisableLevelTruncation` field to `true`.
* When outputting to a TTY, it's often helpful to visually scan down a column where all the levels are the same width. Setting the `PadLevelText` field to `true` enables this behavior, by adding padding to the level text.
- * All options are listed in the [generated docs](https://pkg.go.dev/github.com/sirupsen/logrus#TextFormatter).
-* `logrus.JSONFormatter`. Logs fields as JSON.
- * All options are listed in the [generated docs](https://pkg.go.dev/github.com/sirupsen/logrus#JSONFormatter).
+* [`logrus.JSONFormatter`](https://pkg.go.dev/github.com/sirupsen/logrus#JSONFormatter)
+ logs fields as JSON.
Third-party logging formatters:
@@ -390,10 +374,12 @@ Third-party logging formatters:
* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure.
* [`powerful-logrus-formatter`](https://github.com/zput/zxcTool). get fileName, log's line number and the latest function's name when print log; Save log to files.
* [`caption-json-formatter`](https://github.com/nolleh/caption_json_formatter). logrus's message json formatter with human-readable caption added.
+* [`easy-logrus-formatter`](https://github.com/WeiZhixiong/easy-logrus-formatter). Provide a user-friendly formatter for logrus.
+* [`redactrus`](https://github.com/ibreakthecloud/redactrus). Redacts sensitive information like password, apikeys, email, etc. from logs.
You can define your formatter by implementing the `Formatter` interface,
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
-`Fields` type (`map[string]interface{}`) with all your fields as well as the
+`Fields` type (`map[string]any`) with all your fields as well as the
default ones (see Entries section above):
```go
@@ -516,4 +502,4 @@ Situations when locking is not needed include:
2) logger.Out is an os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allows multi-thread/multi-process writing)
- (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)
+ (Refer to )
diff --git a/vendor/github.com/sirupsen/logrus/alt_exit.go b/vendor/github.com/sirupsen/logrus/alt_exit.go
index 8fd189e1..1c35cf81 100644
--- a/vendor/github.com/sirupsen/logrus/alt_exit.go
+++ b/vendor/github.com/sirupsen/logrus/alt_exit.go
@@ -57,7 +57,7 @@ func Exit(code int) {
//
// This method is useful when a caller wishes to use logrus to log a fatal
// message but also needs to gracefully shutdown. An example usecase could be
-// closing database connections, or sending a alert that the application is
+// closing database connections, or sending an alert that the application is
// closing.
func RegisterExitHandler(handler func()) {
handlers = append(handlers, handler)
@@ -69,7 +69,7 @@ func RegisterExitHandler(handler func()) {
//
// This method is useful when a caller wishes to use logrus to log a fatal
// message but also needs to gracefully shutdown. An example usecase could be
-// closing database connections, or sending a alert that the application is
+// closing database connections, or sending an alert that the application is
// closing.
func DeferExitHandler(handler func()) {
handlers = append([]func(){handler}, handlers...)
diff --git a/vendor/github.com/sirupsen/logrus/buffer_pool.go b/vendor/github.com/sirupsen/logrus/buffer_pool.go
index c7787f77..6b562d87 100644
--- a/vendor/github.com/sirupsen/logrus/buffer_pool.go
+++ b/vendor/github.com/sirupsen/logrus/buffer_pool.go
@@ -5,9 +5,13 @@ import (
"sync"
)
-var (
- bufferPool BufferPool
-)
+var bufferPool BufferPool = &defaultPool{
+ pool: &sync.Pool{
+ New: func() any {
+ return new(bytes.Buffer)
+ },
+ },
+}
type BufferPool interface {
Put(*bytes.Buffer)
@@ -27,17 +31,7 @@ func (p *defaultPool) Get() *bytes.Buffer {
}
// SetBufferPool allows to replace the default logrus buffer pool
-// to better meets the specific needs of an application.
+// to better meet the specific needs of an application.
func SetBufferPool(bp BufferPool) {
bufferPool = bp
}
-
-func init() {
- SetBufferPool(&defaultPool{
- pool: &sync.Pool{
- New: func() interface{} {
- return new(bytes.Buffer)
- },
- },
- })
-}
diff --git a/vendor/github.com/sirupsen/logrus/doc.go b/vendor/github.com/sirupsen/logrus/doc.go
index da67aba0..75186dc2 100644
--- a/vendor/github.com/sirupsen/logrus/doc.go
+++ b/vendor/github.com/sirupsen/logrus/doc.go
@@ -1,25 +1,25 @@
/*
Package logrus is a structured logger for Go, completely API compatible with the standard library logger.
-
The simplest way to use Logrus is simply the package-level exported logger:
- package main
+ package main
- import (
- log "github.com/sirupsen/logrus"
- )
+ import (
+ log "github.com/sirupsen/logrus"
+ )
- func main() {
- log.WithFields(log.Fields{
- "animal": "walrus",
- "number": 1,
- "size": 10,
- }).Info("A walrus appears")
- }
+ func main() {
+ log.WithFields(log.Fields{
+ "animal": "walrus",
+ "number": 1,
+ "size": 10,
+ }).Info("A walrus appears")
+ }
Output:
- time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
+
+ time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
For a full guide visit https://github.com/sirupsen/logrus
*/
diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go
index 71d796d0..82de41f9 100644
--- a/vendor/github.com/sirupsen/logrus/entry.go
+++ b/vendor/github.com/sirupsen/logrus/entry.go
@@ -4,9 +4,11 @@ import (
"bytes"
"context"
"fmt"
+ "maps"
"os"
"reflect"
"runtime"
+ "strconv"
"strings"
"sync"
"time"
@@ -17,8 +19,10 @@ var (
// qualified package name, cached at first use
logrusPackage string
- // Positions in the call stack when tracing to report the calling method
- minimumCallerDepth int
+ // Positions in the call stack when tracing to report the calling method.
+ //
+ // Start at the bottom of the stack before the package-name cache is primed.
+ minimumCallerDepth = 1
// Used for caller information initialisation
callerInitOnce sync.Once
@@ -29,68 +33,116 @@ const (
knownLogrusFrames int = 4
)
-func init() {
- // start at the bottom of the stack before the package-name cache is primed
- minimumCallerDepth = 1
-}
-
// ErrorKey defines the key when adding errors using [WithError], [Logger.WithError].
var ErrorKey = "error"
-// Entry is the final or intermediate Logrus logging entry. It contains all
-// the fields passed with WithField{,s}. It's finally logged when Trace, Debug,
-// Info, Warn, Error, Fatal or Panic is called on it. These objects can be
-// reused and passed around as much as you wish to avoid field duplication.
+// Entry represents a single log event. It may be either an intermediate
+// entry (created via WithField(s), WithContext, etc.) or a final entry
+// that is emitted when one of the level methods (Trace, Debug, Info,
+// Warn, Error, Fatal, Panic) is called.
//
-//nolint:recvcheck // the methods of "Entry" use pointer receiver and non-pointer receiver.
+// An Entry always belongs to a Logger. A nil Logger is invalid and will
+// cause a panic when the entry is logged. Use [NewEntry] or Logger methods
+// to construct entries.
+//
+// Entries are safe to reuse for adding fields and may be passed around
+// to avoid field duplication. Each log operation operates on a copy
+// of the Entry’s data to avoid mutation during formatting.
+//
+//nolint:recvcheck // Entry methods intentionally use both pointer and value receivers.
type Entry struct {
+ // Logger is the Logger that owns this entry and is responsible for
+ // formatting, hooks, and output. It must not be nil. An Entry without
+ // a Logger is invalid and will panic when logged.
Logger *Logger
- // Contains all the fields set by the user.
+ // Data contains all user-defined fields attached to this entry.
Data Fields
- // Time at which the log entry was created
+ // Time is the timestamp for the log event. If zero when the entry is
+ // logged, it defaults to the current time.
Time time.Time
- // Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic
- // This field will be set on entry firing and the value will be equal to the one in Logger struct field.
+ // Level is the severity of the log entry. It is set when the entry
+ // is fired and reflects the level used for that log call.
Level Level
- // Calling method, with package name
+ // Caller contains the calling method information.
+ //
+ // When [Logger.ReportCaller] is enabled, Caller is populated automatically at
+ // log time if it is nil. Hooks and formatters may inspect Caller.
+ //
+ // Applications generally should not modify Caller unless they intentionally
+ // want to provide custom caller information.
Caller *runtime.Frame
- // Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
+ // Message is the log message supplied to one of the logging methods
+ // (Trace, Debug, Info, Warn, Error, Fatal, or Panic). It is set when
+ // the entry is logged.
Message string
- // When formatter is called in entry.log(), a Buffer may be set to entry
+ // Buffer is a reusable buffer provided to the formatter. It is set
+ // before formatting in the normal log path; when nil, formatters
+ // allocate their own.
Buffer *bytes.Buffer
- // Contains the context set by the user. Useful for hook processing etc.
+ // Context carries user-provided context for hooks and formatters.
Context context.Context
- // err may contain a field formatting error
+ // err contains internal field-formatting errors.
err string
}
+// NewEntry creates a new [Entry] associated with the provided Logger.
+// The logger must not be nil. Passing a nil logger results in a
+// panic when a logging method (e.g., [Entry.Info], [Entry.Error], etc.)
+// is called.
func NewEntry(logger *Logger) *Entry {
return &Entry{
Logger: logger,
- // Default is three fields, plus one optional. Give a little extra room.
- Data: make(Fields, 6),
+ // Reserve default predefined fields and a little extra room.
+ Data: make(Fields, defaultFields+3),
}
}
+// Dup creates a copy of the entry for further modification.
+//
+// Data is cloned to avoid mutating the original entry. Other fields
+// (Logger, Time, Context, etc.) are copied by value.
func (entry *Entry) Dup() *Entry {
- data := make(Fields, len(entry.Data))
- for k, v := range entry.Data {
- data[k] = v
+ dup := entry.dup()
+ dup.Data = maps.Clone(entry.Data)
+ return dup
+}
+
+// dup copies the entry fields shared by derived entries except Data, which
+// callers must copy or initialize as appropriate for their use.
+func (entry *Entry) dup() *Entry {
+ return &Entry{
+ Logger: entry.Logger,
+ Time: entry.Time,
+ Caller: entry.Caller,
+ Context: entry.Context,
+ err: entry.err,
}
- return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, Context: entry.Context, err: entry.err}
}
// Bytes returns the bytes representation of this entry from the formatter.
func (entry *Entry) Bytes() ([]byte, error) {
- return entry.Logger.Formatter.Format(entry)
+ // Snapshot the formatter under the lock to protect against concurrent
+ // SetFormatter calls, then release the lock before formatting.
+ // This avoids a data race and prevents a deadlock if Format() triggers
+ // reentrant logging (e.g., a field's MarshalJSON calls logrus).
+ //
+ // See:
+ //
+ // - https://github.com/sirupsen/logrus/issues/1440
+ // - https://github.com/sirupsen/logrus/issues/1448
+ entry.Logger.mu.Lock()
+ formatter := entry.Logger.Formatter
+ entry.Logger.mu.Unlock()
+
+ return formatter.Format(entry)
}
// String returns the string representation from the reader and ultimately the
@@ -112,58 +164,61 @@ func (entry *Entry) WithError(err error) *Entry {
// WithContext adds a context to the Entry.
func (entry *Entry) WithContext(ctx context.Context) *Entry {
- dataCopy := make(Fields, len(entry.Data))
- for k, v := range entry.Data {
- dataCopy[k] = v
- }
- return &Entry{Logger: entry.Logger, Data: dataCopy, Time: entry.Time, err: entry.err, Context: ctx}
+ dup := entry.dup()
+ dup.Data = maps.Clone(entry.Data)
+ dup.Context = ctx
+ return dup
}
// WithField adds a single field to the Entry.
-func (entry *Entry) WithField(key string, value interface{}) *Entry {
- return entry.WithFields(Fields{key: value})
+func (entry *Entry) WithField(key string, value any) *Entry {
+ dup := entry.dup()
+ dup.Data = maps.Clone(entry.Data)
+ dup.addField(key, value)
+ return dup
}
// WithFields adds a map of fields to the Entry.
func (entry *Entry) WithFields(fields Fields) *Entry {
- data := make(Fields, len(entry.Data)+len(fields))
- for k, v := range entry.Data {
- data[k] = v
+ dup := entry.dup()
+ dup.Data = make(Fields, len(entry.Data)+len(fields))
+ maps.Copy(dup.Data, entry.Data)
+
+ for key, value := range fields {
+ dup.addField(key, value)
}
- fieldErr := entry.err
- for k, v := range fields {
- isErrField := false
- if t := reflect.TypeOf(v); t != nil {
- switch {
- case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func:
- isErrField = true
- }
- }
- if isErrField {
- tmp := fmt.Sprintf("can not add field %q", k)
- if fieldErr != "" {
- fieldErr = entry.err + ", " + tmp
+ return dup
+}
+
+// WithTime overrides the time of the Entry.
+func (entry *Entry) WithTime(t time.Time) *Entry {
+ dup := entry.dup()
+ dup.Data = maps.Clone(entry.Data)
+ dup.Time = t
+ return dup
+}
+
+func (entry *Entry) addField(key string, value any) {
+ if _, ok := value.(error); !ok {
+ t := reflect.TypeOf(value)
+ if t != nil && (t.Kind() == reflect.Func || t.Kind() == reflect.Pointer && t.Elem().Kind() == reflect.Func) {
+ if entry.err != "" {
+ entry.err += ", skipping unsupported field " + strconv.Quote(key)
} else {
- fieldErr = tmp
+ entry.err = "skipping unsupported field " + strconv.Quote(key)
}
- } else {
- data[k] = v
+ return
}
}
- return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context}
-}
-// WithTime overrides the time of the Entry.
-func (entry *Entry) WithTime(t time.Time) *Entry {
- dataCopy := make(Fields, len(entry.Data))
- for k, v := range entry.Data {
- dataCopy[k] = v
+ if entry.Data == nil {
+ entry.Data = make(Fields, 1)
}
- return &Entry{Logger: entry.Logger, Data: dataCopy, Time: t, err: entry.err, Context: entry.Context}
+ entry.Data[key] = value
}
// getPackageName reduces a fully qualified function name to the package name
-// There really ought to be to be a better way...
+// There really ought to be a better way...
func getPackageName(f string) string {
for {
lastPeriod := strings.LastIndex(f, ".")
@@ -186,7 +241,7 @@ func getCaller() *runtime.Frame {
_ = runtime.Callers(0, pcs)
// dynamic get the package name and the minimum caller depth
- for i := 0; i < maximumCallerDepth; i++ {
+ for i := range maximumCallerDepth {
funcName := runtime.FuncForPC(pcs[i]).Name()
if strings.Contains(funcName, "getCaller") {
logrusPackage = getPackageName(funcName)
@@ -215,16 +270,47 @@ func getCaller() *runtime.Frame {
return nil
}
-func (entry Entry) HasCaller() (has bool) {
- return entry.Logger != nil &&
- entry.Logger.ReportCaller &&
- entry.Caller != nil
+// HasCaller reports whether this Entry contains caller information.
+//
+// Caller may be set explicitly, or populated at log time when
+// [Logger.ReportCaller] is enabled.
+//
+// Deprecated: use [Entry.Caller] != nil instead.
+//
+//go:fix inline
+func (entry Entry) HasCaller() bool {
+ return entry.Caller != nil
}
-func (entry *Entry) log(level Level, msg string) {
- var buffer *bytes.Buffer
+func (entry *Entry) logArgs(level Level, panicAfter bool, args ...any) {
+ entry.log(level, panicAfter, sprint(args...))
+}
- newEntry := entry.Dup()
+func (entry *Entry) logf(level Level, panicAfter bool, format string, args ...any) {
+ entry.log(level, panicAfter, fmt.Sprintf(format, args...))
+}
+
+// logln uses Sprintln for multiple arguments to preserve Println-style
+// spacing between args, then trims the trailing newline.
+func (entry *Entry) logln(level Level, panicAfter bool, args ...any) {
+ if len(args) <= 1 {
+ entry.log(level, panicAfter, sprint(args...))
+ return
+ }
+ msg := fmt.Sprintln(args...)
+ msg = msg[:len(msg)-1] // Trim the newline added by Sprintln; logging adds its own.
+ entry.log(level, panicAfter, msg)
+}
+
+// log writes msg at level. If panicAfter is true, it panics with the fully
+// populated entry after hooks and output have completed.
+//
+// The explicit flag keeps panic behavior limited to Panic, Panicf, and
+// Panicln while avoiding a return value used only as the panic value.
+// See #1283 and commits f96066e and 5f8c666.
+func (entry *Entry) log(level Level, panicAfter bool, msg string) {
+ newEntry := entry.dup()
+ newEntry.Data = maps.Clone(entry.Data)
if newEntry.Time.IsZero() {
newEntry.Time = time.Now()
@@ -233,17 +319,24 @@ func (entry *Entry) log(level Level, msg string) {
newEntry.Level = level
newEntry.Message = msg
- newEntry.Logger.mu.Lock()
- reportCaller := newEntry.Logger.ReportCaller
+ logger := newEntry.Logger
+ logger.mu.Lock()
+ reportCaller := logger.ReportCaller
bufPool := newEntry.getBufferPool()
- newEntry.Logger.mu.Unlock()
+ logger.mu.Unlock()
- if reportCaller {
+ // Preserve explicitly set caller information.
+ if reportCaller && newEntry.Caller == nil {
newEntry.Caller = getCaller()
}
- newEntry.fireHooks()
- buffer = bufPool.Get()
+ // Select hooks based on the level for this log call. Hooks receive the
+ // Entry and may mutate it, but that does not affect which hooks are
+ // fired for this event.
+ hooks := logger.hooksForLevel(level)
+ newEntry.fireHooks(hooks)
+
+ buffer := bufPool.Get()
defer func() {
newEntry.Buffer = nil
buffer.Reset()
@@ -251,15 +344,12 @@ func (entry *Entry) log(level Level, msg string) {
}()
buffer.Reset()
newEntry.Buffer = buffer
-
newEntry.write()
-
newEntry.Buffer = nil
- // To avoid Entry#log() returning a value that only would make sense for
- // panic() to use in Entry#Panic(), we avoid the allocation by checking
- // directly here.
- if level <= PanicLevel {
+ // Panic here so the panic value contains the fully populated entry without
+ // requiring log to return it to the caller.
+ if panicAfter {
panic(newEntry)
}
}
@@ -271,175 +361,207 @@ func (entry *Entry) getBufferPool() (pool BufferPool) {
return bufferPool
}
-func (entry *Entry) fireHooks() {
- var tmpHooks LevelHooks
- entry.Logger.mu.Lock()
- tmpHooks = make(LevelHooks, len(entry.Logger.Hooks))
- for k, v := range entry.Logger.Hooks {
- tmpHooks[k] = v
- }
- entry.Logger.mu.Unlock()
-
- err := tmpHooks.Fire(entry.Level, entry)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
+func (entry *Entry) fireHooks(hooks []Hook) {
+ for _, hook := range hooks {
+ if err := hook.Fire(entry); err != nil {
+ _, _ = fmt.Fprintln(os.Stderr, "Failed to fire hook:", err)
+ return
+ }
}
}
func (entry *Entry) write() {
+ // Snapshot the formatter under the lock to protect against concurrent
+ // SetFormatter calls, then release the lock before formatting.
+ // This avoids a deadlock when Format() triggers reentrant logging (e.g.,
+ // a field's MarshalJSON calls logrus). See #1448, #1440.
entry.Logger.mu.Lock()
- defer entry.Logger.mu.Unlock()
- serialized, err := entry.Logger.Formatter.Format(entry)
+ formatter := entry.Logger.Formatter
+ entry.Logger.mu.Unlock()
+
+ serialized, err := formatter.Format(entry)
if err != nil {
- fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
+ _, _ = fmt.Fprintln(os.Stderr, "Failed to format entry:", err)
return
}
+
+ // Re-acquire the lock to serialize writes to the underlying io.Writer.
+ entry.Logger.mu.Lock()
+ defer entry.Logger.mu.Unlock()
if _, err := entry.Logger.Out.Write(serialized); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
+ _, _ = fmt.Fprintln(os.Stderr, "Failed to write to log:", err)
}
}
-// Log will log a message at the level given as parameter.
-// Warning: using Log at Panic or Fatal level will not respectively Panic nor Exit.
-// For this behaviour Entry.Panic or Entry.Fatal should be used instead.
-func (entry *Entry) Log(level Level, args ...interface{}) {
+// Log logs a message at the specified level.
+//
+// Using Log with [PanicLevel] or [FatalLevel] intentionally does not
+// trigger a panic or exit. Log treats the level as logging severity only;
+// use [Entry.Panic] or [Entry.Fatal] when those side effects are desired.
+func (entry *Entry) Log(level Level, args ...any) {
+ const panicAfter = false
if entry.Logger.IsLevelEnabled(level) {
- entry.log(level, fmt.Sprint(args...))
+ entry.logArgs(level, panicAfter, args...)
}
}
-func (entry *Entry) Trace(args ...interface{}) {
+func (entry *Entry) Trace(args ...any) {
entry.Log(TraceLevel, args...)
}
-func (entry *Entry) Debug(args ...interface{}) {
+func (entry *Entry) Debug(args ...any) {
entry.Log(DebugLevel, args...)
}
-func (entry *Entry) Print(args ...interface{}) {
+func (entry *Entry) Print(args ...any) {
entry.Info(args...)
}
-func (entry *Entry) Info(args ...interface{}) {
+func (entry *Entry) Info(args ...any) {
entry.Log(InfoLevel, args...)
}
-func (entry *Entry) Warn(args ...interface{}) {
+func (entry *Entry) Warn(args ...any) {
entry.Log(WarnLevel, args...)
}
-func (entry *Entry) Warning(args ...interface{}) {
+func (entry *Entry) Warning(args ...any) {
entry.Warn(args...)
}
-func (entry *Entry) Error(args ...interface{}) {
+func (entry *Entry) Error(args ...any) {
entry.Log(ErrorLevel, args...)
}
-func (entry *Entry) Fatal(args ...interface{}) {
+func (entry *Entry) Fatal(args ...any) {
entry.Log(FatalLevel, args...)
entry.Logger.Exit(1)
}
-func (entry *Entry) Panic(args ...interface{}) {
- entry.Log(PanicLevel, args...)
+func (entry *Entry) Panic(args ...any) {
+ const panicAfter = true
+ if entry.Logger.IsLevelEnabled(PanicLevel) {
+ entry.logArgs(PanicLevel, panicAfter, args...)
+ }
}
// Entry Printf family functions
-func (entry *Entry) Logf(level Level, format string, args ...interface{}) {
+// Logf logs a formatted message at the specified level.
+//
+// Using Logf with [PanicLevel] or [FatalLevel] intentionally does not
+// trigger a panic or exit. Logf treats the level as logging severity only;
+// use [Entry.Panicf] or [Entry.Fatalf] when those side effects are desired.
+func (entry *Entry) Logf(level Level, format string, args ...any) {
+ const panicAfter = false
if entry.Logger.IsLevelEnabled(level) {
- entry.Log(level, fmt.Sprintf(format, args...))
+ entry.logf(level, panicAfter, format, args...)
}
}
-func (entry *Entry) Tracef(format string, args ...interface{}) {
+func (entry *Entry) Tracef(format string, args ...any) {
entry.Logf(TraceLevel, format, args...)
}
-func (entry *Entry) Debugf(format string, args ...interface{}) {
+func (entry *Entry) Debugf(format string, args ...any) {
entry.Logf(DebugLevel, format, args...)
}
-func (entry *Entry) Infof(format string, args ...interface{}) {
+func (entry *Entry) Infof(format string, args ...any) {
entry.Logf(InfoLevel, format, args...)
}
-func (entry *Entry) Printf(format string, args ...interface{}) {
+func (entry *Entry) Printf(format string, args ...any) {
entry.Infof(format, args...)
}
-func (entry *Entry) Warnf(format string, args ...interface{}) {
+func (entry *Entry) Warnf(format string, args ...any) {
entry.Logf(WarnLevel, format, args...)
}
-func (entry *Entry) Warningf(format string, args ...interface{}) {
+func (entry *Entry) Warningf(format string, args ...any) {
entry.Warnf(format, args...)
}
-func (entry *Entry) Errorf(format string, args ...interface{}) {
+func (entry *Entry) Errorf(format string, args ...any) {
entry.Logf(ErrorLevel, format, args...)
}
-func (entry *Entry) Fatalf(format string, args ...interface{}) {
+func (entry *Entry) Fatalf(format string, args ...any) {
entry.Logf(FatalLevel, format, args...)
entry.Logger.Exit(1)
}
-func (entry *Entry) Panicf(format string, args ...interface{}) {
- entry.Logf(PanicLevel, format, args...)
+func (entry *Entry) Panicf(format string, args ...any) {
+ const panicAfter = true
+ if entry.Logger.IsLevelEnabled(PanicLevel) {
+ entry.logf(PanicLevel, panicAfter, format, args...)
+ }
}
// Entry Println family functions
-func (entry *Entry) Logln(level Level, args ...interface{}) {
+// Logln logs a message at the specified level with Println-style spacing.
+//
+// Using Logln with [PanicLevel] or [FatalLevel] intentionally does not
+// trigger a panic or exit. Logln treats the level as logging severity only;
+// use [Entry.Panicln] or [Entry.Fatalln] when those side effects are desired.
+func (entry *Entry) Logln(level Level, args ...any) {
+ const panicAfter = false
if entry.Logger.IsLevelEnabled(level) {
- entry.Log(level, entry.sprintlnn(args...))
+ entry.logln(level, panicAfter, args...)
}
}
-func (entry *Entry) Traceln(args ...interface{}) {
+func (entry *Entry) Traceln(args ...any) {
entry.Logln(TraceLevel, args...)
}
-func (entry *Entry) Debugln(args ...interface{}) {
+func (entry *Entry) Debugln(args ...any) {
entry.Logln(DebugLevel, args...)
}
-func (entry *Entry) Infoln(args ...interface{}) {
+func (entry *Entry) Infoln(args ...any) {
entry.Logln(InfoLevel, args...)
}
-func (entry *Entry) Println(args ...interface{}) {
+func (entry *Entry) Println(args ...any) {
entry.Infoln(args...)
}
-func (entry *Entry) Warnln(args ...interface{}) {
+func (entry *Entry) Warnln(args ...any) {
entry.Logln(WarnLevel, args...)
}
-func (entry *Entry) Warningln(args ...interface{}) {
+func (entry *Entry) Warningln(args ...any) {
entry.Warnln(args...)
}
-func (entry *Entry) Errorln(args ...interface{}) {
+func (entry *Entry) Errorln(args ...any) {
entry.Logln(ErrorLevel, args...)
}
-func (entry *Entry) Fatalln(args ...interface{}) {
+func (entry *Entry) Fatalln(args ...any) {
entry.Logln(FatalLevel, args...)
entry.Logger.Exit(1)
}
-func (entry *Entry) Panicln(args ...interface{}) {
- entry.Logln(PanicLevel, args...)
+func (entry *Entry) Panicln(args ...any) {
+ const panicAfter = true
+ if entry.Logger.IsLevelEnabled(PanicLevel) {
+ entry.logln(PanicLevel, panicAfter, args...)
+ }
}
-// sprintlnn => Sprint no newline. This is to get the behavior of how
-// fmt.Sprintln where spaces are always added between operands, regardless of
-// their type. Instead of vendoring the Sprintln implementation to spare a
-// string allocation, we do the simplest thing.
-func (entry *Entry) sprintlnn(args ...interface{}) string {
- msg := fmt.Sprintln(args...)
- return msg[:len(msg)-1]
+// sprint is fmt.Sprint with fast paths for zero or one string argument.
+func sprint(args ...any) string {
+ switch len(args) {
+ case 0:
+ return ""
+ case 1:
+ if msg, ok := args[0].(string); ok {
+ return msg
+ }
+ }
+ return fmt.Sprint(args...)
}
diff --git a/vendor/github.com/sirupsen/logrus/exported.go b/vendor/github.com/sirupsen/logrus/exported.go
index 017c30ce..8b261c12 100644
--- a/vendor/github.com/sirupsen/logrus/exported.go
+++ b/vendor/github.com/sirupsen/logrus/exported.go
@@ -6,11 +6,12 @@ import (
"time"
)
-var (
- // std is the name of the standard logger in stdlib `log`
- std = New()
-)
+// std is the package-level standard logger, similar to the default logger
+// in the stdlib [log] package.
+var std = New()
+// StandardLogger returns the package-level standard logger used by
+// the top-level logging functions.
func StandardLogger() *Logger {
return std
}
@@ -41,7 +42,7 @@ func GetLevel() Level {
return std.GetLevel()
}
-// IsLevelEnabled checks if the log level of the standard logger is greater than the level param
+// IsLevelEnabled checks if logging for the given level is enabled for the standard logger.
func IsLevelEnabled(level Level) bool {
return std.IsLevelEnabled(level)
}
@@ -51,9 +52,10 @@ func AddHook(hook Hook) {
std.AddHook(hook)
}
-// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
+// WithError creates an entry from the standard logger and adds an error to it,
+// using the value defined in [ErrorKey] as key.
func WithError(err error) *Entry {
- return std.WithField(ErrorKey, err)
+ return std.WithError(err)
}
// WithContext creates an entry from the standard logger and adds a context to it.
@@ -61,210 +63,203 @@ func WithContext(ctx context.Context) *Entry {
return std.WithContext(ctx)
}
-// WithField creates an entry from the standard logger and adds a field to
-// it. If you want multiple fields, use `WithFields`.
-//
-// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
-// or Panic on the Entry it returns.
-func WithField(key string, value interface{}) *Entry {
+// WithField creates an entry from the standard logger and adds a single field.
+// For multiple fields, prefer [WithFields] over chaining WithField calls.
+func WithField(key string, value any) *Entry {
return std.WithField(key, value)
}
-// WithFields creates an entry from the standard logger and adds multiple
-// fields to it. This is simply a helper for `WithField`, invoking it
-// once for each field.
-//
-// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
-// or Panic on the Entry it returns.
+// WithFields creates an entry from the standard logger and adds the fields to it.
func WithFields(fields Fields) *Entry {
return std.WithFields(fields)
}
-// WithTime creates an entry from the standard logger and overrides the time of
-// logs generated with it.
-//
-// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
-// or Panic on the Entry it returns.
+// WithTime creates an entry from the standard logger and overrides the time
+// used for logs generated with it.
func WithTime(t time.Time) *Entry {
return std.WithTime(t)
}
-// Trace logs a message at level Trace on the standard logger.
-func Trace(args ...interface{}) {
+// Trace logs a message at level [TraceLevel] on the standard logger.
+func Trace(args ...any) {
std.Trace(args...)
}
-// Debug logs a message at level Debug on the standard logger.
-func Debug(args ...interface{}) {
+// Debug logs a message at level [DebugLevel] on the standard logger.
+func Debug(args ...any) {
std.Debug(args...)
}
-// Print logs a message at level Info on the standard logger.
-func Print(args ...interface{}) {
+// Print logs a message at level [InfoLevel] on the standard logger.
+func Print(args ...any) {
std.Print(args...)
}
-// Info logs a message at level Info on the standard logger.
-func Info(args ...interface{}) {
+// Info logs a message at level [InfoLevel] on the standard logger.
+func Info(args ...any) {
std.Info(args...)
}
-// Warn logs a message at level Warn on the standard logger.
-func Warn(args ...interface{}) {
+// Warn logs a message at level [WarnLevel] on the standard logger.
+func Warn(args ...any) {
std.Warn(args...)
}
-// Warning logs a message at level Warn on the standard logger.
-func Warning(args ...interface{}) {
+// Warning logs a message at level [WarnLevel] on the standard logger.
+func Warning(args ...any) {
std.Warning(args...)
}
-// Error logs a message at level Error on the standard logger.
-func Error(args ...interface{}) {
+// Error logs a message at level [ErrorLevel] on the standard logger.
+func Error(args ...any) {
std.Error(args...)
}
-// Panic logs a message at level Panic on the standard logger.
-func Panic(args ...interface{}) {
+// Panic logs a message at level [PanicLevel] on the standard logger.
+func Panic(args ...any) {
std.Panic(args...)
}
-// Fatal logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
-func Fatal(args ...interface{}) {
+// Fatal logs a message at level [FatalLevel] on the standard logger,
+// then exits the process with status 1.
+func Fatal(args ...any) {
std.Fatal(args...)
}
-// TraceFn logs a message from a func at level Trace on the standard logger.
+// TraceFn logs a message from a func at level [TraceLevel] on the standard logger.
func TraceFn(fn LogFunction) {
std.TraceFn(fn)
}
-// DebugFn logs a message from a func at level Debug on the standard logger.
+// DebugFn logs a message from a func at level [DebugLevel] on the standard logger.
func DebugFn(fn LogFunction) {
std.DebugFn(fn)
}
-// PrintFn logs a message from a func at level Info on the standard logger.
+// PrintFn logs a message from a func at level [InfoLevel] on the standard logger.
func PrintFn(fn LogFunction) {
std.PrintFn(fn)
}
-// InfoFn logs a message from a func at level Info on the standard logger.
+// InfoFn logs a message from a func at level [InfoLevel] on the standard logger.
func InfoFn(fn LogFunction) {
std.InfoFn(fn)
}
-// WarnFn logs a message from a func at level Warn on the standard logger.
+// WarnFn logs a message from a func at level [WarnLevel] on the standard logger.
func WarnFn(fn LogFunction) {
std.WarnFn(fn)
}
-// WarningFn logs a message from a func at level Warn on the standard logger.
+// WarningFn logs a message from a func at level [WarnLevel] on the standard logger.
func WarningFn(fn LogFunction) {
std.WarningFn(fn)
}
-// ErrorFn logs a message from a func at level Error on the standard logger.
+// ErrorFn logs a message from a func at level [ErrorLevel] on the standard logger.
func ErrorFn(fn LogFunction) {
std.ErrorFn(fn)
}
-// PanicFn logs a message from a func at level Panic on the standard logger.
+// PanicFn logs a message from a func at level [PanicLevel] on the standard logger.
func PanicFn(fn LogFunction) {
std.PanicFn(fn)
}
-// FatalFn logs a message from a func at level Fatal on the standard logger then the process will exit with status set to 1.
+// FatalFn logs a message from a func at level [FatalLevel] on the standard logger,
+// then exits the process with status 1.
func FatalFn(fn LogFunction) {
std.FatalFn(fn)
}
-// Tracef logs a message at level Trace on the standard logger.
-func Tracef(format string, args ...interface{}) {
+// Tracef logs a message at level [TraceLevel] on the standard logger.
+func Tracef(format string, args ...any) {
std.Tracef(format, args...)
}
-// Debugf logs a message at level Debug on the standard logger.
-func Debugf(format string, args ...interface{}) {
+// Debugf logs a message at level [DebugLevel] on the standard logger.
+func Debugf(format string, args ...any) {
std.Debugf(format, args...)
}
-// Printf logs a message at level Info on the standard logger.
-func Printf(format string, args ...interface{}) {
+// Printf logs a message at level [InfoLevel] on the standard logger.
+func Printf(format string, args ...any) {
std.Printf(format, args...)
}
-// Infof logs a message at level Info on the standard logger.
-func Infof(format string, args ...interface{}) {
+// Infof logs a message at level [InfoLevel] on the standard logger.
+func Infof(format string, args ...any) {
std.Infof(format, args...)
}
-// Warnf logs a message at level Warn on the standard logger.
-func Warnf(format string, args ...interface{}) {
+// Warnf logs a message at level [WarnLevel] on the standard logger.
+func Warnf(format string, args ...any) {
std.Warnf(format, args...)
}
-// Warningf logs a message at level Warn on the standard logger.
-func Warningf(format string, args ...interface{}) {
+// Warningf logs a message at level [WarnLevel] on the standard logger.
+func Warningf(format string, args ...any) {
std.Warningf(format, args...)
}
-// Errorf logs a message at level Error on the standard logger.
-func Errorf(format string, args ...interface{}) {
+// Errorf logs a message at level [ErrorLevel] on the standard logger.
+func Errorf(format string, args ...any) {
std.Errorf(format, args...)
}
-// Panicf logs a message at level Panic on the standard logger.
-func Panicf(format string, args ...interface{}) {
+// Panicf logs a message at level [PanicLevel] on the standard logger.
+func Panicf(format string, args ...any) {
std.Panicf(format, args...)
}
-// Fatalf logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
-func Fatalf(format string, args ...interface{}) {
+// Fatalf logs a message at level [FatalLevel] on the standard logger,
+// then exits the process with status 1.
+func Fatalf(format string, args ...any) {
std.Fatalf(format, args...)
}
-// Traceln logs a message at level Trace on the standard logger.
-func Traceln(args ...interface{}) {
+// Traceln logs a message at level [TraceLevel] on the standard logger.
+func Traceln(args ...any) {
std.Traceln(args...)
}
-// Debugln logs a message at level Debug on the standard logger.
-func Debugln(args ...interface{}) {
+// Debugln logs a message at level [DebugLevel] on the standard logger.
+func Debugln(args ...any) {
std.Debugln(args...)
}
-// Println logs a message at level Info on the standard logger.
-func Println(args ...interface{}) {
+// Println logs a message at level [InfoLevel] on the standard logger.
+func Println(args ...any) {
std.Println(args...)
}
-// Infoln logs a message at level Info on the standard logger.
-func Infoln(args ...interface{}) {
+// Infoln logs a message at level [InfoLevel] on the standard logger.
+func Infoln(args ...any) {
std.Infoln(args...)
}
-// Warnln logs a message at level Warn on the standard logger.
-func Warnln(args ...interface{}) {
+// Warnln logs a message at level [WarnLevel] on the standard logger.
+func Warnln(args ...any) {
std.Warnln(args...)
}
-// Warningln logs a message at level Warn on the standard logger.
-func Warningln(args ...interface{}) {
+// Warningln logs a message at level [WarnLevel] on the standard logger.
+func Warningln(args ...any) {
std.Warningln(args...)
}
-// Errorln logs a message at level Error on the standard logger.
-func Errorln(args ...interface{}) {
+// Errorln logs a message at level [ErrorLevel] on the standard logger.
+func Errorln(args ...any) {
std.Errorln(args...)
}
-// Panicln logs a message at level Panic on the standard logger.
-func Panicln(args ...interface{}) {
+// Panicln logs a message at level [PanicLevel] on the standard logger.
+func Panicln(args ...any) {
std.Panicln(args...)
}
-// Fatalln logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
-func Fatalln(args ...interface{}) {
+// Fatalln logs a message at level [FatalLevel] on the standard logger,
+// then exits the process with status 1.
+func Fatalln(args ...any) {
std.Fatalln(args...)
}
diff --git a/vendor/github.com/sirupsen/logrus/formatter.go b/vendor/github.com/sirupsen/logrus/formatter.go
index 40888377..16f2e0e0 100644
--- a/vendor/github.com/sirupsen/logrus/formatter.go
+++ b/vendor/github.com/sirupsen/logrus/formatter.go
@@ -2,27 +2,40 @@ package logrus
import "time"
-// Default key names for the default fields
const (
+ // defaultTimestampFormat is the layout used to format entry timestamps
+ // when a formatter has not specified a custom TimestampFormat.
+ // It follows time.RFC3339 and is applied unless timestamps are disabled.
defaultTimestampFormat = time.RFC3339
- FieldKeyMsg = "msg"
- FieldKeyLevel = "level"
- FieldKeyTime = "time"
- FieldKeyLogrusError = "logrus_error"
- FieldKeyFunc = "func"
- FieldKeyFile = "file"
+
+ // defaultFields is the number of commonly included predefined log entry fields
+ // (msg, level, time). It is used as a capacity hint when constructing
+ // intermediate collections during formatting (for example, the fixed key list).
+ //
+ // It does not include the optional "logrus_error", "func", or "file" fields.
+ defaultFields = 3
+)
+
+// Default key names for the default fields
+const (
+ FieldKeyMsg = "msg"
+ FieldKeyLevel = "level"
+ FieldKeyTime = "time"
+ FieldKeyLogrusError = "logrus_error"
+ FieldKeyFunc = "func"
+ FieldKeyFile = "file"
)
-// The Formatter interface is used to implement a custom Formatter. It takes an
-// `Entry`. It exposes all the fields, including the default ones:
+// Formatter is implemented by types that format log entries. It receives an
+// [*Entry], which contains:
//
-// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
-// * `entry.Data["time"]`. The timestamp.
-// * `entry.Data["level"]. The level the entry was logged at.
+// - entry.Message: the message passed to logging methods such as [Info], [Warn], [Error]
+// - entry.Time: the timestamp
+// - entry.Level: the log level
//
-// Any additional fields added with `WithField` or `WithFields` are also in
-// `entry.Data`. Format is expected to return an array of bytes which are then
-// logged to `logger.Out`.
+// Additional fields added with [WithField] or [WithFields] are available in
+// [Entry.Data]. Format should return the formatted log entry as a byte slice,
+// which is written to [Logger.Out].
type Formatter interface {
Format(*Entry) ([]byte, error)
}
@@ -30,12 +43,12 @@ type Formatter interface {
// This is to not silently overwrite `time`, `msg`, `func` and `level` fields when
// dumping it. If this code wasn't there doing:
//
-// logrus.WithField("level", 1).Info("hello")
+// logrus.WithField("level", 1).Info("hello")
//
// Would just silently drop the user provided level. Instead with this code
// it'll logged as:
//
-// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
+// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
//
// It's not exported because it's still using Data in an opinionated way. It's to
// avoid code duplication between the two default formatters.
diff --git a/vendor/github.com/sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go
index c96dc563..fac7695e 100644
--- a/vendor/github.com/sirupsen/logrus/json_formatter.go
+++ b/vendor/github.com/sirupsen/logrus/json_formatter.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"runtime"
+ "strconv"
)
type fieldKey string
@@ -20,7 +21,13 @@ func (f FieldMap) resolve(key fieldKey) string {
return string(key)
}
-// JSONFormatter formats logs into parsable json
+// JSONFormatter formats logs into parsable JSON.
+//
+// Fields from [Entry.Data] are included in the JSON object together with the
+// standard fields derived from the entry. If a field conflicts with a standard
+// field, it is prefixed with "fields.". Standard field names can be customized
+// through FieldMap. When DataKey is set, fields from [Entry.Data] are nested
+// under that key instead.
type JSONFormatter struct {
// TimestampFormat sets the format used for marshaling timestamps.
// The format to use is the same than for time.Format or time.Parse from the standard
@@ -61,7 +68,8 @@ type JSONFormatter struct {
// Format renders a single log entry
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
- data := make(Fields, len(entry.Data)+4)
+ caller := entry.Caller
+ data := make(Fields, len(entry.Data)+defaultFields)
for k, v := range entry.Data {
switch v := v.(type) {
case error:
@@ -73,13 +81,14 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
}
}
- if f.DataKey != "" {
- newData := make(Fields, 4)
+ if f.DataKey != "" && len(entry.Data) > 0 {
+ newData := make(Fields, defaultFields+1)
newData[f.DataKey] = data
data = newData
}
- prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
+ hasCaller := caller != nil
+ prefixFieldClashes(data, f.FieldMap, hasCaller)
timestampFormat := f.TimestampFormat
if timestampFormat == "" {
@@ -94,11 +103,13 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
}
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
- if entry.HasCaller() {
- funcVal := entry.Caller.Function
- fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
+ if caller != nil {
+ var funcVal, fileVal string
if f.CallerPrettyfier != nil {
- funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
+ funcVal, fileVal = f.CallerPrettyfier(caller)
+ } else {
+ funcVal = caller.Function
+ fileVal = caller.File + ":" + strconv.FormatInt(int64(caller.Line), 10)
}
if funcVal != "" {
data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
@@ -108,11 +119,9 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
}
}
- var b *bytes.Buffer
- if entry.Buffer != nil {
- b = entry.Buffer
- } else {
- b = &bytes.Buffer{}
+ b := entry.Buffer
+ if b == nil {
+ b = new(bytes.Buffer)
}
encoder := json.NewEncoder(b)
diff --git a/vendor/github.com/sirupsen/logrus/level.go b/vendor/github.com/sirupsen/logrus/level.go
new file mode 100644
index 00000000..7bd4255d
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/level.go
@@ -0,0 +1,101 @@
+package logrus
+
+import (
+ "strings"
+ "sync"
+)
+
+const (
+ ansiReset = "\x1b[0m" // reset attributes
+ ansiRed = "\x1b[31m" // red
+ ansiYellow = "\x1b[33m" // yellow
+ ansiCyan = "\x1b[36m" // cyan
+ ansiDimCyan = "\x1b[2;36m" // dim cyan
+ ansiDimWhite = "\x1b[2;37m" // dim white (light gray)
+)
+
+type lvlPrefix struct {
+ full string
+ truncated string
+ padded string
+}
+
+func colorize(level Level, s string) string {
+ color := ansiCyan
+ switch level {
+ case TraceLevel:
+ color = ansiDimWhite
+ case DebugLevel:
+ color = ansiDimCyan
+ case WarnLevel:
+ color = ansiYellow
+ case ErrorLevel, FatalLevel, PanicLevel:
+ color = ansiRed
+ case InfoLevel:
+ color = ansiCyan
+ }
+ return color + s + ansiReset
+}
+
+func formatLevel(level Level, disableTrunc, pad bool, maxLen int) string {
+ upper := strings.ToUpper(level.String())
+
+ if pad && maxLen > len(upper) {
+ upper += strings.Repeat(" ", maxLen-len(upper))
+ }
+
+ if !pad && !disableTrunc && len(upper) > 4 {
+ upper = upper[:4]
+ }
+
+ return colorize(level, upper)
+}
+
+var levelPrefixOnce = sync.OnceValues(func() (map[Level]lvlPrefix, lvlPrefix) {
+ var maxLevel Level
+ maxLen := 0
+ for _, lvl := range AllLevels {
+ if lvl > maxLevel {
+ maxLevel = lvl
+ }
+ if l := len(lvl.String()); l > maxLen {
+ maxLen = l
+ }
+ }
+
+ prefix := make(map[Level]lvlPrefix, len(AllLevels))
+ for _, lvl := range AllLevels {
+ prefix[lvl] = lvlPrefix{
+ full: formatLevel(lvl, true, false, maxLen),
+ truncated: formatLevel(lvl, false, false, maxLen),
+ padded: formatLevel(lvl, true, true, maxLen),
+ }
+ }
+
+ unknownLevel := maxLevel + 1
+ unknown := lvlPrefix{
+ full: formatLevel(unknownLevel, true, false, maxLen),
+ truncated: formatLevel(unknownLevel, false, false, maxLen),
+ padded: formatLevel(unknownLevel, true, true, maxLen),
+ }
+
+ return prefix, unknown
+})
+
+func levelPrefix(level Level, disableTrunc, pad bool) string {
+ prefix, unknown := levelPrefixOnce()
+
+ p, ok := prefix[level]
+ if !ok {
+ p = unknown
+ }
+
+ switch {
+ case pad:
+ return p.padded
+ case !disableTrunc:
+ return p.truncated
+ default:
+ return p.full
+ }
+}
diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go
index f5b8c439..17a46e6a 100644
--- a/vendor/github.com/sirupsen/logrus/logger.go
+++ b/vendor/github.com/sirupsen/logrus/logger.go
@@ -12,17 +12,19 @@ import (
// LogFunction For big messages, it can be more efficient to pass a function
// and only call it if the log level is actually enables rather than
// generating the log message and then checking if the level is enabled
-type LogFunction func() []interface{}
+type LogFunction func() []any
type Logger struct {
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
// file, or leave it default which is `os.Stderr`. You can also set this to
// something more adventurous, such as logging to Kafka.
Out io.Writer
+
// Hooks for the logger instance. These allow firing events based on logging
// levels and log entries. For example, to send errors to an error tracking
// service, log to StatsD or dump the core on fatal errors.
Hooks LevelHooks
+
// All log entries pass through the formatter before logged to Out. The
// included formatters are `TextFormatter` and `JSONFormatter` for which
// TextFormatter is the default. In development (when a TTY is attached) it
@@ -38,37 +40,44 @@ type Logger struct {
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
// logged.
Level Level
+
// Used to sync writing to the log. Locking is enabled by Default
- mu MutexWrap
+ mu mutexWrap
+
// Reusable empty entry
entryPool sync.Pool
+
// Function to exit the application, defaults to `os.Exit()`
- ExitFunc exitFunc
+ ExitFunc func(int)
+
// The buffer pool used to format the log. If it is nil, the default global
// buffer pool will be used.
BufferPool BufferPool
}
-type exitFunc func(int)
+// MutexWrap is the mutex implementation used by [Logger].
+//
+// Deprecated: MutexWrap is an implementation detail of Logger and should not be used directly.
+type MutexWrap = mutexWrap
-type MutexWrap struct {
+type mutexWrap struct {
lock sync.Mutex
disabled bool
}
-func (mw *MutexWrap) Lock() {
+func (mw *mutexWrap) Lock() {
if !mw.disabled {
mw.lock.Lock()
}
}
-func (mw *MutexWrap) Unlock() {
+func (mw *mutexWrap) Unlock() {
if !mw.disabled {
mw.lock.Unlock()
}
}
-func (mw *MutexWrap) Disable() {
+func (mw *mutexWrap) Disable() {
mw.disabled = true
}
@@ -104,7 +113,7 @@ func (logger *Logger) newEntry() *Entry {
}
func (logger *Logger) releaseEntry(entry *Entry) {
- entry.Data = map[string]interface{}{}
+ entry.Data = map[string]any{}
logger.entryPool.Put(entry)
}
@@ -112,7 +121,7 @@ func (logger *Logger) releaseEntry(entry *Entry) {
// Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to
// this new returned entry.
// If you want multiple fields, use `WithFields`.
-func (logger *Logger) WithField(key string, value interface{}) *Entry {
+func (logger *Logger) WithField(key string, value any) *Entry {
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.WithField(key, value)
@@ -148,7 +157,12 @@ func (logger *Logger) WithTime(t time.Time) *Entry {
return entry.WithTime(t)
}
-func (logger *Logger) Logf(level Level, format string, args ...interface{}) {
+// Logf logs a formatted message at the specified level.
+//
+// Using Logf with [PanicLevel] or [FatalLevel] intentionally does not
+// trigger a panic or exit. Logf treats the level as logging severity only;
+// use [Logger.Panicf] or [Logger.Fatalf] when those side effects are desired.
+func (logger *Logger) Logf(level Level, format string, args ...any) {
if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
entry.Logf(level, format, args...)
@@ -156,49 +170,55 @@ func (logger *Logger) Logf(level Level, format string, args ...interface{}) {
}
}
-func (logger *Logger) Tracef(format string, args ...interface{}) {
+func (logger *Logger) Tracef(format string, args ...any) {
logger.Logf(TraceLevel, format, args...)
}
-func (logger *Logger) Debugf(format string, args ...interface{}) {
+func (logger *Logger) Debugf(format string, args ...any) {
logger.Logf(DebugLevel, format, args...)
}
-func (logger *Logger) Infof(format string, args ...interface{}) {
+func (logger *Logger) Infof(format string, args ...any) {
logger.Logf(InfoLevel, format, args...)
}
-func (logger *Logger) Printf(format string, args ...interface{}) {
+func (logger *Logger) Printf(format string, args ...any) {
entry := logger.newEntry()
entry.Printf(format, args...)
logger.releaseEntry(entry)
}
-func (logger *Logger) Warnf(format string, args ...interface{}) {
+func (logger *Logger) Warnf(format string, args ...any) {
logger.Logf(WarnLevel, format, args...)
}
-func (logger *Logger) Warningf(format string, args ...interface{}) {
+func (logger *Logger) Warningf(format string, args ...any) {
logger.Warnf(format, args...)
}
-func (logger *Logger) Errorf(format string, args ...interface{}) {
+func (logger *Logger) Errorf(format string, args ...any) {
logger.Logf(ErrorLevel, format, args...)
}
-func (logger *Logger) Fatalf(format string, args ...interface{}) {
+func (logger *Logger) Fatalf(format string, args ...any) {
logger.Logf(FatalLevel, format, args...)
logger.Exit(1)
}
-func (logger *Logger) Panicf(format string, args ...interface{}) {
- logger.Logf(PanicLevel, format, args...)
+func (logger *Logger) Panicf(format string, args ...any) {
+ if logger.IsLevelEnabled(PanicLevel) {
+ entry := logger.newEntry()
+ defer logger.releaseEntry(entry)
+ entry.Panicf(format, args...)
+ }
}
-// Log will log a message at the level given as parameter.
-// Warning: using Log at Panic or Fatal level will not respectively Panic nor Exit.
-// For this behaviour Logger.Panic or Logger.Fatal should be used instead.
-func (logger *Logger) Log(level Level, args ...interface{}) {
+// Log logs a message at the specified level.
+//
+// Using Log with [PanicLevel] or [FatalLevel] intentionally does not
+// trigger a panic or exit. Log treats the level as logging severity only;
+// use [Logger.Panic] or [Logger.Fatal] when those side effects are desired.
+func (logger *Logger) Log(level Level, args ...any) {
if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
entry.Log(level, args...)
@@ -206,6 +226,11 @@ func (logger *Logger) Log(level Level, args ...interface{}) {
}
}
+// LogFn logs a message returned by fn at the specified level.
+//
+// Using LogFn with [PanicLevel] or [FatalLevel] intentionally does not
+// trigger a panic or exit. LogFn treats the level as logging severity only;
+// use [Logger.PanicFn] or [Logger.FatalFn] when those side effects are desired.
func (logger *Logger) LogFn(level Level, fn LogFunction) {
if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
@@ -214,43 +239,47 @@ func (logger *Logger) LogFn(level Level, fn LogFunction) {
}
}
-func (logger *Logger) Trace(args ...interface{}) {
+func (logger *Logger) Trace(args ...any) {
logger.Log(TraceLevel, args...)
}
-func (logger *Logger) Debug(args ...interface{}) {
+func (logger *Logger) Debug(args ...any) {
logger.Log(DebugLevel, args...)
}
-func (logger *Logger) Info(args ...interface{}) {
+func (logger *Logger) Info(args ...any) {
logger.Log(InfoLevel, args...)
}
-func (logger *Logger) Print(args ...interface{}) {
+func (logger *Logger) Print(args ...any) {
entry := logger.newEntry()
entry.Print(args...)
logger.releaseEntry(entry)
}
-func (logger *Logger) Warn(args ...interface{}) {
+func (logger *Logger) Warn(args ...any) {
logger.Log(WarnLevel, args...)
}
-func (logger *Logger) Warning(args ...interface{}) {
+func (logger *Logger) Warning(args ...any) {
logger.Warn(args...)
}
-func (logger *Logger) Error(args ...interface{}) {
+func (logger *Logger) Error(args ...any) {
logger.Log(ErrorLevel, args...)
}
-func (logger *Logger) Fatal(args ...interface{}) {
+func (logger *Logger) Fatal(args ...any) {
logger.Log(FatalLevel, args...)
logger.Exit(1)
}
-func (logger *Logger) Panic(args ...interface{}) {
- logger.Log(PanicLevel, args...)
+func (logger *Logger) Panic(args ...any) {
+ if logger.IsLevelEnabled(PanicLevel) {
+ entry := logger.newEntry()
+ defer logger.releaseEntry(entry)
+ entry.Panic(args...)
+ }
}
func (logger *Logger) TraceFn(fn LogFunction) {
@@ -289,10 +318,19 @@ func (logger *Logger) FatalFn(fn LogFunction) {
}
func (logger *Logger) PanicFn(fn LogFunction) {
- logger.LogFn(PanicLevel, fn)
+ if logger.IsLevelEnabled(PanicLevel) {
+ entry := logger.newEntry()
+ defer logger.releaseEntry(entry)
+ entry.Panic(fn()...)
+ }
}
-func (logger *Logger) Logln(level Level, args ...interface{}) {
+// Logln logs a message at the specified level with Println-style spacing.
+//
+// Using Logln with [PanicLevel] or [FatalLevel] intentionally does not
+// trigger a panic or exit. Logln treats the level as logging severity only;
+// use [Logger.Panicln] or [Logger.Fatalln] when those side effects are desired.
+func (logger *Logger) Logln(level Level, args ...any) {
if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
entry.Logln(level, args...)
@@ -300,43 +338,47 @@ func (logger *Logger) Logln(level Level, args ...interface{}) {
}
}
-func (logger *Logger) Traceln(args ...interface{}) {
+func (logger *Logger) Traceln(args ...any) {
logger.Logln(TraceLevel, args...)
}
-func (logger *Logger) Debugln(args ...interface{}) {
+func (logger *Logger) Debugln(args ...any) {
logger.Logln(DebugLevel, args...)
}
-func (logger *Logger) Infoln(args ...interface{}) {
+func (logger *Logger) Infoln(args ...any) {
logger.Logln(InfoLevel, args...)
}
-func (logger *Logger) Println(args ...interface{}) {
+func (logger *Logger) Println(args ...any) {
entry := logger.newEntry()
entry.Println(args...)
logger.releaseEntry(entry)
}
-func (logger *Logger) Warnln(args ...interface{}) {
+func (logger *Logger) Warnln(args ...any) {
logger.Logln(WarnLevel, args...)
}
-func (logger *Logger) Warningln(args ...interface{}) {
+func (logger *Logger) Warningln(args ...any) {
logger.Warnln(args...)
}
-func (logger *Logger) Errorln(args ...interface{}) {
+func (logger *Logger) Errorln(args ...any) {
logger.Logln(ErrorLevel, args...)
}
-func (logger *Logger) Fatalln(args ...interface{}) {
+func (logger *Logger) Fatalln(args ...any) {
logger.Logln(FatalLevel, args...)
logger.Exit(1)
}
-func (logger *Logger) Panicln(args ...interface{}) {
- logger.Logln(PanicLevel, args...)
+func (logger *Logger) Panicln(args ...any) {
+ if logger.IsLevelEnabled(PanicLevel) {
+ entry := logger.newEntry()
+ defer logger.releaseEntry(entry)
+ entry.Panicln(args...)
+ }
}
func (logger *Logger) Exit(code int) {
@@ -375,7 +417,22 @@ func (logger *Logger) AddHook(hook Hook) {
logger.Hooks.Add(hook)
}
-// IsLevelEnabled checks if the log level of the logger is greater than the level param
+// hooksForLevel returns a snapshot of the hooks registered for the given level.
+// The returned slice is a shallow copy and may be used without holding logger.mu.
+func (logger *Logger) hooksForLevel(level Level) []Hook {
+ logger.mu.Lock()
+ hooks := logger.Hooks[level]
+ if len(hooks) == 0 {
+ logger.mu.Unlock()
+ return nil
+ }
+ out := make([]Hook, len(hooks))
+ copy(out, hooks)
+ logger.mu.Unlock()
+ return out
+}
+
+// IsLevelEnabled checks if logging for the given level is enabled.
func (logger *Logger) IsLevelEnabled(level Level) bool {
return logger.level() >= level
}
@@ -394,6 +451,7 @@ func (logger *Logger) SetOutput(output io.Writer) {
logger.Out = output
}
+// SetReportCaller sets whether the caller stack frame must be logged.
func (logger *Logger) SetReportCaller(reportCaller bool) {
logger.mu.Lock()
defer logger.mu.Unlock()
@@ -403,9 +461,9 @@ func (logger *Logger) SetReportCaller(reportCaller bool) {
// ReplaceHooks replaces the logger hooks and returns the old ones
func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks {
logger.mu.Lock()
+ defer logger.mu.Unlock()
oldHooks := logger.Hooks
logger.Hooks = hooks
- logger.mu.Unlock()
return oldHooks
}
diff --git a/vendor/github.com/sirupsen/logrus/logrus.go b/vendor/github.com/sirupsen/logrus/logrus.go
index 37fc4fef..d52b4ba7 100644
--- a/vendor/github.com/sirupsen/logrus/logrus.go
+++ b/vendor/github.com/sirupsen/logrus/logrus.go
@@ -1,13 +1,13 @@
package logrus
import (
+ "bytes"
"fmt"
"log"
- "strings"
)
// Fields type, used to pass to [WithFields].
-type Fields map[string]interface{}
+type Fields map[string]any
// Level type
//
@@ -16,39 +16,56 @@ type Level uint32
// Convert the Level to a string. E.g. [PanicLevel] becomes "panic".
func (level Level) String() string {
- if b, err := level.MarshalText(); err == nil {
- return string(b)
- } else {
+ switch level {
+ case TraceLevel:
+ return "trace"
+ case DebugLevel:
+ return "debug"
+ case InfoLevel:
+ return "info"
+ case WarnLevel:
+ return "warning"
+ case ErrorLevel:
+ return "error"
+ case FatalLevel:
+ return "fatal"
+ case PanicLevel:
+ return "panic"
+ default:
return "unknown"
}
}
// ParseLevel takes a string level and returns the Logrus log level constant.
func ParseLevel(lvl string) (Level, error) {
- switch strings.ToLower(lvl) {
- case "panic":
+ return parseLevel([]byte(lvl))
+}
+
+func parseLevel(b []byte) (Level, error) {
+ switch {
+ case bytes.EqualFold(b, []byte("panic")):
return PanicLevel, nil
- case "fatal":
+ case bytes.EqualFold(b, []byte("fatal")):
return FatalLevel, nil
- case "error":
+ case bytes.EqualFold(b, []byte("error")):
return ErrorLevel, nil
- case "warn", "warning":
+ case bytes.EqualFold(b, []byte("warn")),
+ bytes.EqualFold(b, []byte("warning")):
return WarnLevel, nil
- case "info":
+ case bytes.EqualFold(b, []byte("info")):
return InfoLevel, nil
- case "debug":
+ case bytes.EqualFold(b, []byte("debug")):
return DebugLevel, nil
- case "trace":
+ case bytes.EqualFold(b, []byte("trace")):
return TraceLevel, nil
+ default:
+ return 0, fmt.Errorf("not a valid logrus Level: %q", b)
}
-
- var l Level
- return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (level *Level) UnmarshalText(text []byte) error {
- l, err := ParseLevel(string(text))
+ l, err := parseLevel(text)
if err != nil {
return err
}
@@ -60,23 +77,11 @@ func (level *Level) UnmarshalText(text []byte) error {
func (level Level) MarshalText() ([]byte, error) {
switch level {
- case TraceLevel:
- return []byte("trace"), nil
- case DebugLevel:
- return []byte("debug"), nil
- case InfoLevel:
- return []byte("info"), nil
- case WarnLevel:
- return []byte("warning"), nil
- case ErrorLevel:
- return []byte("error"), nil
- case FatalLevel:
- return []byte("fatal"), nil
- case PanicLevel:
- return []byte("panic"), nil
+ case TraceLevel, DebugLevel, InfoLevel, WarnLevel, ErrorLevel, FatalLevel, PanicLevel:
+ return []byte(level.String()), nil
+ default:
+ return nil, fmt.Errorf("not a valid logrus level %d", level)
}
-
- return nil, fmt.Errorf("not a valid logrus level %d", level)
}
// AllLevels exposing all logging levels.
@@ -91,7 +96,7 @@ var AllLevels = []Level{
}
// These are the different logging levels. You can set the logging level to log
-// on your instance of logger, obtained with `logrus.New()`.
+// on your instance of logger, obtained with [logrus.New].
const (
// PanicLevel level, highest level of severity. Logs and then calls panic with the
// message passed to Debug, Info, ...
@@ -113,78 +118,110 @@ const (
TraceLevel
)
-// Won't compile if StdLogger can't be realized by a log.Logger
+// Compile-time interface assertions.
var (
- _ StdLogger = &log.Logger{}
- _ StdLogger = &Entry{}
- _ StdLogger = &Logger{}
+ _ StdLogger = (*log.Logger)(nil)
+ _ StdLogger = (*Entry)(nil)
+ _ StdLogger = (*Logger)(nil)
+
+ _ FieldLogger = (*Logger)(nil)
+ _ FieldLogger = (*Entry)(nil)
+ _ FieldLogger = Ext1FieldLogger(nil)
+
+ _ DebugLogger = (*Logger)(nil)
+ _ InfoLogger = (*Logger)(nil)
+ _ WarnLogger = (*Logger)(nil)
+ _ ErrorLogger = (*Logger)(nil)
+ _ TraceLogger = (*Logger)(nil)
+
+ _ DebugLogger = (*Entry)(nil)
+ _ InfoLogger = (*Entry)(nil)
+ _ WarnLogger = (*Entry)(nil)
+ _ ErrorLogger = (*Entry)(nil)
+ _ TraceLogger = (*Entry)(nil)
+
+ _ Ext1FieldLogger = (*Logger)(nil)
+ _ Ext1FieldLogger = (*Entry)(nil)
)
// StdLogger is what your logrus-enabled library should take, that way
// it'll accept a stdlib logger ([log.Logger]) and a logrus logger.
// There's no standard interface, so this is the closest we get, unfortunately.
type StdLogger interface {
- Print(...interface{})
- Printf(string, ...interface{})
- Println(...interface{})
+ Print(args ...any)
+ Printf(format string, args ...any)
+ Println(args ...any)
- Fatal(...interface{})
- Fatalf(string, ...interface{})
- Fatalln(...interface{})
+ Fatal(args ...any)
+ Fatalf(format string, args ...any)
+ Fatalln(args ...any)
- Panic(...interface{})
- Panicf(string, ...interface{})
- Panicln(...interface{})
+ Panic(args ...any)
+ Panicf(format string, args ...any)
+ Panicln(args ...any)
}
// FieldLogger extends the [StdLogger] interface, generalizing
// the [Entry] and [Logger] types.
type FieldLogger interface {
- WithField(key string, value interface{}) *Entry
+ WithField(key string, value any) *Entry
WithFields(fields Fields) *Entry
WithError(err error) *Entry
- Debugf(format string, args ...interface{})
- Infof(format string, args ...interface{})
- Printf(format string, args ...interface{})
- Warnf(format string, args ...interface{})
- Warningf(format string, args ...interface{})
- Errorf(format string, args ...interface{})
- Fatalf(format string, args ...interface{})
- Panicf(format string, args ...interface{})
-
- Debug(args ...interface{})
- Info(args ...interface{})
- Print(args ...interface{})
- Warn(args ...interface{})
- Warning(args ...interface{})
- Error(args ...interface{})
- Fatal(args ...interface{})
- Panic(args ...interface{})
-
- Debugln(args ...interface{})
- Infoln(args ...interface{})
- Println(args ...interface{})
- Warnln(args ...interface{})
- Warningln(args ...interface{})
- Errorln(args ...interface{})
- Fatalln(args ...interface{})
- Panicln(args ...interface{})
-
- // IsDebugEnabled() bool
- // IsInfoEnabled() bool
- // IsWarnEnabled() bool
- // IsErrorEnabled() bool
- // IsFatalEnabled() bool
- // IsPanicEnabled() bool
+ StdLogger
+ DebugLogger
+ InfoLogger
+ WarnLogger
+ ErrorLogger
+
+ // Legacy warning aliases. These are kept on FieldLogger for backwards
+ // compatibility, but are intentionally omitted from [WarnLogger].
+
+ Warning(args ...any)
+ Warningf(format string, args ...any)
+ Warningln(args ...any)
+}
+
+// DebugLogger provides convenience functions to log messages at level [DebugLevel].
+type DebugLogger interface {
+ Debug(args ...any)
+ Debugf(format string, args ...any)
+ Debugln(args ...any)
+}
+
+// InfoLogger provides convenience functions to log messages at level [InfoLevel].
+type InfoLogger interface {
+ Info(args ...any)
+ Infof(format string, args ...any)
+ Infoln(args ...any)
+}
+
+// WarnLogger provides convenience functions to log messages at level [WarnLevel].
+type WarnLogger interface {
+ Warn(args ...any)
+ Warnf(format string, args ...any)
+ Warnln(args ...any)
+}
+
+// ErrorLogger provides convenience functions to log messages at level [ErrorLevel].
+type ErrorLogger interface {
+ Error(args ...any)
+ Errorf(format string, args ...any)
+ Errorln(args ...any)
+}
+
+// TraceLogger provides convenience functions to log messages at level [TraceLevel].
+type TraceLogger interface {
+ Trace(args ...any)
+ Tracef(format string, args ...any)
+ Traceln(args ...any)
}
-// Ext1FieldLogger (the first extension to [FieldLogger]) is superfluous, it is
-// here for consistency. Do not use. Use [FieldLogger], [Logger] or [Entry]
-// instead.
+// Ext1FieldLogger is FieldLogger extended with Trace-level methods.
+//
+// New code should prefer the smallest applicable interface, such as
+// [FieldLogger] or [TraceLogger], or use [Logger] or [Entry] directly.
type Ext1FieldLogger interface {
FieldLogger
- Tracef(format string, args ...interface{})
- Trace(args ...interface{})
- Traceln(args ...interface{})
+ TraceLogger
}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go
index 2403de98..1c6202b8 100644
--- a/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go
@@ -1,11 +1,7 @@
-// +build appengine
+//go:build appengine
package logrus
-import (
- "io"
-)
-
-func checkIfTerminal(w io.Writer) bool {
+func checkIfTerminal(_ any) bool {
return true
}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
index 69956b42..ff9531ac 100644
--- a/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
@@ -1,5 +1,4 @@
-// +build darwin dragonfly freebsd netbsd openbsd hurd
-// +build !js
+//go:build (darwin || dragonfly || freebsd || netbsd || openbsd || hurd) && !tinygo
package logrus
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_js.go b/vendor/github.com/sirupsen/logrus/terminal_check_js.go
deleted file mode 100644
index ebdae3ec..00000000
--- a/vendor/github.com/sirupsen/logrus/terminal_check_js.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// +build js
-
-package logrus
-
-func isTerminal(fd int) bool {
- return false
-}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go b/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go
index 97af92c6..17ae9f04 100644
--- a/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go
@@ -1,11 +1,7 @@
-// +build js nacl plan9
+//go:build js || nacl || plan9 || wasi || wasip1 || tinygo
package logrus
-import (
- "io"
-)
-
-func checkIfTerminal(w io.Writer) bool {
+func checkIfTerminal(_ any) bool {
return false
}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go
index 3293fb3c..780a42a5 100644
--- a/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go
@@ -1,4 +1,4 @@
-// +build !appengine,!js,!windows,!nacl,!plan9
+//go:build !appengine && !js && !windows && !nacl && !plan9 && !wasi && !wasip1 && !tinygo
package logrus
@@ -10,7 +10,11 @@ import (
func checkIfTerminal(w io.Writer) bool {
switch v := w.(type) {
case *os.File:
- return isTerminal(int(v.Fd()))
+ fd := v.Fd()
+ if fd > uintptr(^uint(0)>>1) {
+ return false
+ }
+ return isTerminal(int(fd))
default:
return false
}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go b/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go
index f6710b3b..8d9b26fc 100644
--- a/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go
@@ -1,3 +1,5 @@
+//go:build solaris && !tinygo
+
package logrus
import (
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
index c9aed267..b161506d 100644
--- a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
@@ -1,7 +1,4 @@
-//go:build (linux || aix || zos) && !js && !wasi
-// +build linux aix zos
-// +build !js
-// +build !wasi
+//go:build (linux || aix || zos) && !tinygo
package logrus
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_wasi.go b/vendor/github.com/sirupsen/logrus/terminal_check_wasi.go
deleted file mode 100644
index 2822b212..00000000
--- a/vendor/github.com/sirupsen/logrus/terminal_check_wasi.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build wasi
-// +build wasi
-
-package logrus
-
-func isTerminal(fd int) bool {
- return false
-}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_wasip1.go b/vendor/github.com/sirupsen/logrus/terminal_check_wasip1.go
deleted file mode 100644
index 108a6be1..00000000
--- a/vendor/github.com/sirupsen/logrus/terminal_check_wasip1.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build wasip1
-// +build wasip1
-
-package logrus
-
-func isTerminal(fd int) bool {
- return false
-}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_windows.go b/vendor/github.com/sirupsen/logrus/terminal_check_windows.go
index 2879eb50..5fd3c431 100644
--- a/vendor/github.com/sirupsen/logrus/terminal_check_windows.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_windows.go
@@ -1,4 +1,4 @@
-// +build !appengine,!js,windows
+//go:build windows && !appengine
package logrus
diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go
index 6dfeb18b..82c1f3da 100644
--- a/vendor/github.com/sirupsen/logrus/text_formatter.go
+++ b/vendor/github.com/sirupsen/logrus/text_formatter.go
@@ -3,30 +3,32 @@ package logrus
import (
"bytes"
"fmt"
+ "maps"
"os"
+ "reflect"
"runtime"
- "sort"
+ "slices"
"strconv"
"strings"
"sync"
"time"
- "unicode/utf8"
)
-const (
- red = 31
- yellow = 33
- blue = 36
- gray = 37
-)
-
-var baseTimestamp time.Time
-
-func init() {
- baseTimestamp = time.Now()
-}
-
-// TextFormatter formats logs into text
+var baseTimestamp = time.Now()
+
+// TextFormatter formats logs into text.
+//
+// Output is logfmt-like: key=value pairs separated by spaces. Fields from
+// [Entry.Data] are included together with the standard fields derived from the
+// entry. If a field conflicts with a standard field, it is prefixed with
+// "fields.". Standard field names can be customized through FieldMap.
+//
+// Field keys are written as-is (unquoted and unescaped) in the plain
+// (non-colored) format; only field values may be quoted depending on
+// DisableQuote, ForceQuote, QuoteEmptyFields, and the value content.
+//
+// When colors are enabled, ANSI escape sequences may be added for presentation.
+// For fully escaped structured output (including safe keys), use JSONFormatter.
type TextFormatter struct {
// Set to true to bypass checking for a TTY before outputting colors.
ForceColors bool
@@ -64,7 +66,7 @@ type TextFormatter struct {
// be desired.
DisableSorting bool
- // The keys sorting function, when uninitialized it uses sort.Strings.
+ // The keys sorting function, when uninitialized it uses slices.Sort.
SortingFunc func([]string)
// Disables the truncation of the level text to 4 characters.
@@ -77,16 +79,22 @@ type TextFormatter struct {
// QuoteEmptyFields will wrap empty fields in quotes if true
QuoteEmptyFields bool
- // Whether the logger's out is to a terminal
- isTerminal bool
+ // Whether the logger's out is to a terminal. Don't use this field
+ // directly; use TextFormatter.isTerminal instead.
+ terminal bool
// FieldMap allows users to customize the names of keys for default fields.
+ // Mapped keys are written as-is, so they should be safe for plain-text output.
+ //
// As an example:
+ //
// formatter := &TextFormatter{
- // FieldMap: FieldMap{
- // FieldKeyTime: "@timestamp",
- // FieldKeyLevel: "@level",
- // FieldKeyMsg: "@message"}}
+ // FieldMap: FieldMap{
+ // FieldKeyTime: "@timestamp",
+ // FieldKeyLevel: "@level",
+ // FieldKeyMsg: "@message",
+ // },
+ // }
FieldMap FieldMap
// CallerPrettyfier can be set by the user to modify the content
@@ -96,54 +104,78 @@ type TextFormatter struct {
CallerPrettyfier func(*runtime.Frame) (function string, file string)
terminalInitOnce sync.Once
-
- // The max length of the level text, generated dynamically on init
- levelTextMaxLength int
}
-func (f *TextFormatter) init(entry *Entry) {
- if entry.Logger != nil {
- f.isTerminal = checkIfTerminal(entry.Logger.Out)
- }
- // Get the max length of the level text
- for _, level := range AllLevels {
- levelTextLength := utf8.RuneCount([]byte(level.String()))
- if levelTextLength > f.levelTextMaxLength {
- f.levelTextMaxLength = levelTextLength
- }
+func (f *TextFormatter) isTerminal(entry *Entry) bool {
+ if entry == nil || entry.Logger == nil {
+ // Don't run the terminalInitOnce without a logger, otherwise we'd
+ // cache the default (false) forever even if a logger is attached
+ // later.
+ return false
}
-}
-func (f *TextFormatter) isColored() bool {
- isColored := f.ForceColors || (f.isTerminal && (runtime.GOOS != "windows"))
+ f.terminalInitOnce.Do(func() {
+ entry.Logger.mu.Lock()
+ out := entry.Logger.Out
+ entry.Logger.mu.Unlock()
- if f.EnvironmentOverrideColors {
- switch force, ok := os.LookupEnv("CLICOLOR_FORCE"); {
- case ok && force != "0":
- isColored = true
- case ok && force == "0", os.Getenv("CLICOLOR") == "0":
- isColored = false
- }
+ f.terminal = checkIfTerminal(out)
+ })
+
+ return f.terminal
+}
+
+func (f *TextFormatter) isColored(isTerminal bool) bool {
+ if f.DisableColors {
+ return false
}
- return isColored && !f.DisableColors
+ colored := f.ForceColors || isTerminal
+ if !f.EnvironmentOverrideColors {
+ return colored
+ }
+ if force, ok := os.LookupEnv("CLICOLOR_FORCE"); ok {
+ return force != "0"
+ }
+ if os.Getenv("CLICOLOR") == "0" {
+ return false
+ }
+ return colored
}
// Format renders a single log entry
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
- data := make(Fields)
- for k, v := range entry.Data {
- data[k] = v
- }
- prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
+ data := make(Fields, len(entry.Data))
+ maps.Copy(data, entry.Data)
+ isColored := f.isColored(f.isTerminal(entry))
+
+ caller := entry.Caller
+ hasCaller := caller != nil
+ prefixFieldClashes(data, f.FieldMap, hasCaller)
keys := make([]string, 0, len(data))
for k := range data {
keys = append(keys, k)
}
- var funcVal, fileVal string
+ b := entry.Buffer
+ if b == nil {
+ b = new(bytes.Buffer)
+ }
+
+ if isColored {
+ f.printColored(b, entry, keys, data)
+ } else {
+ f.printPlain(b, entry, keys, data)
+ }
+
+ return b.Bytes(), nil
+}
+
+func (f *TextFormatter) printPlain(b *bytes.Buffer, entry *Entry, keys []string, data Fields) {
+ caller := entry.Caller
+ hasCaller := caller != nil
- fixedKeys := make([]string, 0, 4+len(data))
+ fixedKeys := make([]string, 0, len(keys)+defaultFields)
if !f.DisableTimestamp {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime))
}
@@ -154,12 +186,14 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
if entry.err != "" {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError))
}
- if entry.HasCaller() {
+
+ var funcVal, fileVal string
+ if caller != nil {
if f.CallerPrettyfier != nil {
- funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
+ funcVal, fileVal = f.CallerPrettyfier(caller)
} else {
- funcVal = entry.Caller.Function
- fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
+ funcVal = caller.Function
+ fileVal = caller.File + ":" + strconv.FormatInt(int64(caller.Line), 10)
}
if funcVal != "" {
@@ -172,169 +206,278 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
if !f.DisableSorting {
if f.SortingFunc == nil {
- sort.Strings(keys)
+ // Default sorting does not sort the "fixed keys";
+ // see https://github.com/sirupsen/logrus/commit/73bc94e60c753099e8bae902f81fbd6e7dd95f26
+ slices.Sort(keys)
fixedKeys = append(fixedKeys, keys...)
} else {
- if !f.isColored() {
- fixedKeys = append(fixedKeys, keys...)
- f.SortingFunc(fixedKeys)
- } else {
- f.SortingFunc(keys)
- }
+ fixedKeys = append(fixedKeys, keys...)
+ f.SortingFunc(fixedKeys)
}
} else {
fixedKeys = append(fixedKeys, keys...)
}
- var b *bytes.Buffer
- if entry.Buffer != nil {
- b = entry.Buffer
- } else {
- b = &bytes.Buffer{}
- }
-
- f.terminalInitOnce.Do(func() { f.init(entry) })
-
- timestampFormat := f.TimestampFormat
- if timestampFormat == "" {
- timestampFormat = defaultTimestampFormat
- }
- if f.isColored() {
- f.printColored(b, entry, keys, data, timestampFormat)
- } else {
-
- for _, key := range fixedKeys {
- var value interface{}
- switch {
- case key == f.FieldMap.resolve(FieldKeyTime):
- value = entry.Time.Format(timestampFormat)
- case key == f.FieldMap.resolve(FieldKeyLevel):
- value = entry.Level.String()
- case key == f.FieldMap.resolve(FieldKeyMsg):
- value = entry.Message
- case key == f.FieldMap.resolve(FieldKeyLogrusError):
- value = entry.err
- case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller():
- value = funcVal
- case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller():
- value = fileVal
- default:
- value = data[key]
+ for _, key := range fixedKeys {
+ var value any
+ switch {
+ case key == f.FieldMap.resolve(FieldKeyTime):
+ if f.TimestampFormat == "" {
+ value = entry.Time.Format(defaultTimestampFormat)
+ } else {
+ value = entry.Time.Format(f.TimestampFormat)
}
- f.appendKeyValue(b, key, value)
+ case key == f.FieldMap.resolve(FieldKeyLevel):
+ value = entry.Level.String()
+ case key == f.FieldMap.resolve(FieldKeyMsg):
+ value = entry.Message
+ case key == f.FieldMap.resolve(FieldKeyLogrusError):
+ value = entry.err
+ case key == f.FieldMap.resolve(FieldKeyFunc) && hasCaller:
+ value = funcVal
+ case key == f.FieldMap.resolve(FieldKeyFile) && hasCaller:
+ value = fileVal
+ default:
+ value = data[key]
}
+ f.appendKeyValue(b, key, value)
}
b.WriteByte('\n')
- return b.Bytes(), nil
}
-func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, data Fields, timestampFormat string) {
- var levelColor int
- switch entry.Level {
- case DebugLevel, TraceLevel:
- levelColor = gray
- case WarnLevel:
- levelColor = yellow
- case ErrorLevel, FatalLevel, PanicLevel:
- levelColor = red
- case InfoLevel:
- levelColor = blue
- default:
- levelColor = blue
- }
-
- levelText := strings.ToUpper(entry.Level.String())
- if !f.DisableLevelTruncation && !f.PadLevelText {
- levelText = levelText[0:4]
- }
- if f.PadLevelText {
- // Generates the format string used in the next line, for example "%-6s" or "%-7s".
- // Based on the max level text length.
- formatString := "%-" + strconv.Itoa(f.levelTextMaxLength) + "s"
- // Formats the level text by appending spaces up to the max length, for example:
- // - "INFO "
- // - "WARNING"
- levelText = fmt.Sprintf(formatString, levelText)
- }
-
+func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, data Fields) {
// Remove a single newline if it already exists in the message to keep
// the behavior of logrus text_formatter the same as the stdlib log package
entry.Message = strings.TrimSuffix(entry.Message, "\n")
- caller := ""
- if entry.HasCaller() {
- funcVal := fmt.Sprintf("%s()", entry.Caller.Function)
- fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
-
+ var callerText string
+ if caller := entry.Caller; caller != nil {
+ var funcVal, fileVal string
if f.CallerPrettyfier != nil {
- funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
+ funcVal, fileVal = f.CallerPrettyfier(caller)
+ } else {
+ if caller.Function != "" {
+ funcVal = caller.Function + "()"
+ }
+ fileVal = caller.File + ":" + strconv.FormatInt(int64(caller.Line), 10)
}
if fileVal == "" {
- caller = funcVal
+ callerText = funcVal
} else if funcVal == "" {
- caller = fileVal
+ callerText = fileVal
} else {
- caller = fileVal + " " + funcVal
+ callerText = fileVal + " " + funcVal
}
}
+ levelText := levelPrefix(entry.Level, f.DisableLevelTruncation, f.PadLevelText)
switch {
case f.DisableTimestamp:
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, entry.Message)
+ _, _ = fmt.Fprintf(b, "%s%s %-44s ", levelText, callerText, entry.Message)
case !f.FullTimestamp:
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message)
+ _, _ = fmt.Fprintf(b, "%s[%04d]%s %-44s ", levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), callerText, entry.Message)
default:
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message)
+ timestampFormat := f.TimestampFormat
+ if timestampFormat == "" {
+ timestampFormat = defaultTimestampFormat
+ }
+ _, _ = fmt.Fprintf(b, "%s[%s]%s %-44s ", levelText, entry.Time.Format(timestampFormat), callerText, entry.Message)
+ }
+
+ if !f.DisableSorting {
+ if f.SortingFunc == nil {
+ slices.Sort(keys)
+ } else {
+ f.SortingFunc(keys)
+ }
}
+
+ // Keys use the same color as the level-prefix.
for _, k := range keys {
- v := data[k]
- fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
- f.appendValue(b, v)
+ b.WriteByte(' ')
+ b.WriteString(colorize(entry.Level, k))
+ b.WriteByte('=')
+ f.appendValue(b, data[k])
}
+
+ b.WriteByte('\n')
}
-func (f *TextFormatter) needsQuoting(text string) bool {
- if f.ForceQuote {
- return true
+// appendKeyValue writes key=value. Keys are written verbatim (unquoted/unescaped);
+// values are subject to quoting/escaping.
+func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value any) {
+ if b.Len() > 0 {
+ b.WriteByte(' ')
}
- if f.QuoteEmptyFields && len(text) == 0 {
- return true
+ b.WriteString(key)
+ b.WriteByte('=')
+ f.appendValue(b, value)
+}
+
+func (f *TextFormatter) appendValue(b *bytes.Buffer, value any) {
+ // Fast paths.
+ switch v := value.(type) {
+ case string:
+ f.appendString(b, v)
+ return
+ case []byte:
+ f.appendBytes(b, v)
+ return
+ case bool:
+ var raw [8]byte
+ f.appendBytes(b, strconv.AppendBool(raw[:0], v))
+ return
+ case error:
+ f.appendError(b, v)
+ return
+ case fmt.Stringer:
+ f.appendStringer(b, v)
+ return
}
- if f.DisableQuote {
- return false
+
+ // Handle common primitives.
+ var raw [64]byte
+ var num []byte
+
+ switch v := value.(type) {
+ case int:
+ num = strconv.AppendInt(raw[:0], int64(v), 10)
+ case int8:
+ num = strconv.AppendInt(raw[:0], int64(v), 10)
+ case int16:
+ num = strconv.AppendInt(raw[:0], int64(v), 10)
+ case int32:
+ num = strconv.AppendInt(raw[:0], int64(v), 10)
+ case int64:
+ num = strconv.AppendInt(raw[:0], v, 10)
+
+ case uint:
+ num = strconv.AppendUint(raw[:0], uint64(v), 10)
+ case uint8:
+ num = strconv.AppendUint(raw[:0], uint64(v), 10)
+ case uint16:
+ num = strconv.AppendUint(raw[:0], uint64(v), 10)
+ case uint32:
+ num = strconv.AppendUint(raw[:0], uint64(v), 10)
+ case uint64:
+ num = strconv.AppendUint(raw[:0], v, 10)
+ case uintptr:
+ num = strconv.AppendUint(raw[:0], uint64(v), 10)
+
+ case float32:
+ num = strconv.AppendFloat(raw[:0], float64(v), 'g', -1, 32)
+ case float64:
+ num = strconv.AppendFloat(raw[:0], v, 'g', -1, 64)
+
+ default:
+ f.appendString(b, fmt.Sprint(value))
+ return
+ }
+
+ f.appendNumeric(b, num)
+}
+
+func (f *TextFormatter) appendString(b *bytes.Buffer, s string) {
+ quote := f.ForceQuote || (f.QuoteEmptyFields && len(s) == 0) || (!f.DisableQuote && needsQuoting(s))
+ if !quote {
+ b.WriteString(s)
+ return
+ }
+ if len(s) == 0 {
+ b.WriteString(`""`)
+ return
+ }
+
+ var tmp [128]byte
+ b.Write(strconv.AppendQuote(tmp[:0], s))
+}
+
+func (f *TextFormatter) appendBytes(b *bytes.Buffer, bs []byte) {
+ quote := f.ForceQuote || (f.QuoteEmptyFields && len(bs) == 0) || (!f.DisableQuote && needsQuotingBytes(bs))
+ if !quote {
+ b.Write(bs)
+ return
+ }
+ if len(bs) == 0 {
+ b.WriteString(`""`)
+ return
+ }
+
+ var tmp [128]byte
+ b.Write(strconv.AppendQuote(tmp[:0], string(bs)))
+}
+
+func (f *TextFormatter) appendNumeric(b *bytes.Buffer, out []byte) {
+ if f.ForceQuote {
+ var tmp [128]byte
+ b.Write(strconv.AppendQuote(tmp[:0], string(out)))
+ return
}
- for _, ch := range text {
- //nolint:staticcheck // QF1001: could apply De Morgan's law
- if !((ch >= 'a' && ch <= 'z') ||
- (ch >= 'A' && ch <= 'Z') ||
- (ch >= '0' && ch <= '9') ||
- ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') {
+ b.Write(out)
+}
+
+func (f *TextFormatter) appendError(b *bytes.Buffer, v error) {
+ defer f.recoverValue(b, v, "Error")
+
+ f.appendString(b, v.Error())
+}
+
+func (f *TextFormatter) appendStringer(b *bytes.Buffer, v fmt.Stringer) {
+ defer f.recoverValue(b, v, "String")
+
+ f.appendString(b, v.String())
+}
+
+func (f *TextFormatter) recoverValue(b *bytes.Buffer, v any, method string) {
+ if r := recover(); r != nil {
+ rv := reflect.ValueOf(v)
+ if rv.Kind() == reflect.Pointer && rv.IsNil() {
+ f.appendString(b, "")
+ } else {
+ f.appendString(b, fmt.Sprintf("%%!v(PANIC=%s method: %v)", method, r))
+ }
+ }
+}
+
+// needsQuoting returns true if the string contains any byte that
+// requires quoting. It returns false when every byte is "safe" according
+// to isSafeByte.
+func needsQuoting(s string) bool {
+ // use an index loop (avoid rune decoding).
+ for i := range len(s) {
+ c := s[i]
+ if !isSafeByte(c) {
return true
}
}
return false
}
-func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
- if b.Len() > 0 {
- b.WriteByte(' ')
+// needsQuotingBytes returns true if the byte slice contains any byte that
+// requires quoting. It returns false when every byte is "safe" according
+// to isSafeByte.
+func needsQuotingBytes(bs []byte) bool {
+ for _, c := range bs {
+ if !isSafeByte(c) {
+ return true
+ }
}
- b.WriteString(key)
- b.WriteByte('=')
- f.appendValue(b, value)
+ return false
}
-func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
- stringVal, ok := value.(string)
- if !ok {
- stringVal = fmt.Sprint(value)
+// isSafeByte returns true if the byte is allowed unquoted (ASCII and in the allowlist).
+// It purposely uses byte arithmetic (no runes) for performance.
+func isSafeByte(ch byte) bool {
+ ok := ch < 0x80 && ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))
+ if ok {
+ return true
}
-
- if !f.needsQuoting(stringVal) {
- b.WriteString(stringVal)
- } else {
- fmt.Fprintf(b, "%q", stringVal)
+ switch ch {
+ case '-', '.', '_', '/', '@', '^', '+':
+ return true
+ default:
+ return false
}
}
diff --git a/vendor/github.com/sirupsen/logrus/writer.go b/vendor/github.com/sirupsen/logrus/writer.go
index 074fd4b8..30e34cda 100644
--- a/vendor/github.com/sirupsen/logrus/writer.go
+++ b/vendor/github.com/sirupsen/logrus/writer.go
@@ -30,7 +30,7 @@ func (entry *Entry) Writer() *io.PipeWriter {
func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
reader, writer := io.Pipe()
- var printFunc func(args ...interface{})
+ printFunc := entry.Print
// Determine which log function to use based on the specified log level
switch level {
@@ -48,8 +48,6 @@ func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
printFunc = entry.Fatal
case PanicLevel:
printFunc = entry.Panic
- default:
- printFunc = entry.Print
}
// Start a new goroutine to scan the input and write it to the logger using the specified print function.
@@ -63,7 +61,7 @@ func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
}
// writerScanner scans the input from the reader and writes it to the logger
-func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
+func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...any)) {
scanner := bufio.NewScanner(reader)
// Set the buffer size to the maximum token size to avoid buffer overflows
diff --git a/vendor/github.com/sourcegraph/go-diff/diff/diff.go b/vendor/github.com/sourcegraph/go-diff/diff/diff.go
index 81aa6557..cc19fe52 100644
--- a/vendor/github.com/sourcegraph/go-diff/diff/diff.go
+++ b/vendor/github.com/sourcegraph/go-diff/diff/diff.go
@@ -5,12 +5,18 @@ import (
"time"
)
+// ParseOptions specifies options for parsing diffs.
+type ParseOptions struct {
+ // KeepCR specifies whether to keep trailing carriage return characters (\r) in lines.
+ KeepCR bool
+}
+
// A FileDiff represents a unified diff for a single file.
//
// A file unified diff has a header that resembles the following:
//
-// --- oldname 2009-10-11 15:12:20.000000000 -0700
-// +++ newname 2009-10-11 15:12:30.000000000 -0700
+// --- oldname 2009-10-11 15:12:20.000000000 -0700
+// +++ newname 2009-10-11 15:12:30.000000000 -0700
type FileDiff struct {
// the original name of the file
OrigName string
diff --git a/vendor/github.com/sourcegraph/go-diff/diff/parse.go b/vendor/github.com/sourcegraph/go-diff/diff/parse.go
index 48eeb967..b73e2301 100644
--- a/vendor/github.com/sourcegraph/go-diff/diff/parse.go
+++ b/vendor/github.com/sourcegraph/go-diff/diff/parse.go
@@ -1,7 +1,6 @@
package diff
import (
- "bufio"
"bytes"
"errors"
"fmt"
@@ -17,13 +16,24 @@ import (
// case of per-file errors. If it cannot detect when the diff of the next file
// begins, the hunks are added to the FileDiff of the previous file.
func ParseMultiFileDiff(diff []byte) ([]*FileDiff, error) {
- return NewMultiFileDiffReader(bytes.NewReader(diff)).ReadAllFiles()
+ return ParseMultiFileDiffOptions(diff, ParseOptions{})
+}
+
+// ParseMultiFileDiffOptions parses a multi-file unified diff with the given options.
+func ParseMultiFileDiffOptions(diff []byte, opts ParseOptions) ([]*FileDiff, error) {
+ return NewMultiFileDiffReaderOptions(bytes.NewReader(diff), opts).ReadAllFiles()
}
// NewMultiFileDiffReader returns a new MultiFileDiffReader that reads
// a multi-file unified diff from r.
func NewMultiFileDiffReader(r io.Reader) *MultiFileDiffReader {
- return &MultiFileDiffReader{reader: newLineReader(r)}
+ return NewMultiFileDiffReaderOptions(r, ParseOptions{})
+}
+
+// NewMultiFileDiffReaderOptions returns a new MultiFileDiffReader that reads
+// a multi-file unified diff from r with the given options.
+func NewMultiFileDiffReaderOptions(r io.Reader, opts ParseOptions) *MultiFileDiffReader {
+ return &MultiFileDiffReader{reader: newLineReaderOptions(r, opts)}
}
// MultiFileDiffReader reads a multi-file unified diff.
@@ -153,13 +163,24 @@ func (r *MultiFileDiffReader) ReadAllFiles() ([]*FileDiff, error) {
// ParseFileDiff parses a file unified diff.
func ParseFileDiff(diff []byte) (*FileDiff, error) {
- return NewFileDiffReader(bytes.NewReader(diff)).Read()
+ return ParseFileDiffOptions(diff, ParseOptions{})
+}
+
+// ParseFileDiffOptions parses a file unified diff with the given options.
+func ParseFileDiffOptions(diff []byte, opts ParseOptions) (*FileDiff, error) {
+ return NewFileDiffReaderOptions(bytes.NewReader(diff), opts).Read()
}
// NewFileDiffReader returns a new FileDiffReader that reads a file
// unified diff.
func NewFileDiffReader(r io.Reader) *FileDiffReader {
- return &FileDiffReader{reader: &lineReader{reader: bufio.NewReader(r)}}
+ return NewFileDiffReaderOptions(r, ParseOptions{})
+}
+
+// NewFileDiffReaderOptions returns a new FileDiffReader that reads a file
+// unified diff with the given options.
+func NewFileDiffReaderOptions(r io.Reader, opts ParseOptions) *FileDiffReader {
+ return &FileDiffReader{reader: newLineReaderOptions(r, opts)}
}
// FileDiffReader reads a unified file diff.
@@ -405,6 +426,7 @@ func readQuotedFilename(text string) (value string, remainder string, err error)
// valid syntax, it may be impossible to extract filenames; if so, the
// function returns ("", "", true).
func parseDiffGitArgs(diffArgs string) (string, string, bool) {
+ diffArgs = strings.TrimSuffix(diffArgs, "\r")
length := len(diffArgs)
if length < 3 {
return "", "", false
@@ -540,6 +562,7 @@ func handleEmpty(fd *FileDiff) (wasEmpty bool) {
return
}
rawFilename := header[len(prefix):]
+ rawFilename = strings.TrimSuffix(rawFilename, "\r")
// extract the filename prefix (e.g. "a/") from the 'diff --git' line.
var prefixLetterIndex int
@@ -586,7 +609,12 @@ var (
// only of hunks and not include a file header; if it has a file
// header, use ParseFileDiff.
func ParseHunks(diff []byte) ([]*Hunk, error) {
- r := NewHunksReader(bytes.NewReader(diff))
+ return ParseHunksOptions(diff, ParseOptions{})
+}
+
+// ParseHunksOptions parses hunks from a unified diff with the given options.
+func ParseHunksOptions(diff []byte, opts ParseOptions) ([]*Hunk, error) {
+ r := NewHunksReaderOptions(bytes.NewReader(diff), opts)
hunks, err := r.ReadAllHunks()
if err != nil {
return nil, err
@@ -597,7 +625,13 @@ func ParseHunks(diff []byte) ([]*Hunk, error) {
// NewHunksReader returns a new HunksReader that reads unified diff hunks
// from r.
func NewHunksReader(r io.Reader) *HunksReader {
- return &HunksReader{reader: &lineReader{reader: bufio.NewReader(r)}}
+ return NewHunksReaderOptions(r, ParseOptions{})
+}
+
+// NewHunksReaderOptions returns a new HunksReader that reads unified diff hunks
+// from r with the given options.
+func NewHunksReaderOptions(r io.Reader, opts ParseOptions) *HunksReader {
+ return &HunksReader{reader: newLineReaderOptions(r, opts)}
}
// A HunksReader reads hunks from a unified diff.
@@ -701,7 +735,7 @@ func (r *HunksReader) ReadHunk() (*Hunk, error) {
// handle that case.
return r.hunk, &ParseError{r.line, r.offset, &ErrBadHunkLine{Line: line}}
}
- if bytes.Equal(line, []byte(noNewlineMessage)) {
+ if bytes.Equal(bytes.TrimSuffix(line, []byte("\r")), []byte(noNewlineMessage)) {
if lastLineFromOrig {
// Retain the newline in the body (otherwise the
// diff line would be like "-a+b", where "+b" is
@@ -755,6 +789,7 @@ func linePrefix(c byte) bool {
// if its value is 1. normalizeHeader returns an error if the header
// is not in the correct format.
func normalizeHeader(header string) (string, string, error) {
+ header = strings.TrimSuffix(header, "\r")
// Split the header into five parts: the first '@@', the two
// ranges, the last '@@', and the optional section.
pieces := strings.SplitN(header, " ", 5)
@@ -815,7 +850,8 @@ func parseOnlyInMessage(line []byte) (bool, []byte, []byte) {
if idx < 0 {
return false, nil, nil
}
- return true, line[:idx], line[idx+2:]
+ filename := bytes.TrimSuffix(line[idx+2:], []byte("\r"))
+ return true, line[:idx], filename
}
// A ParseError is a description of a unified diff syntax error.
diff --git a/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go b/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go
index 45300252..3356283d 100644
--- a/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go
+++ b/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go
@@ -13,6 +13,13 @@ func newLineReader(r io.Reader) *lineReader {
return &lineReader{reader: bufio.NewReader(r)}
}
+func newLineReaderOptions(r io.Reader, opts ParseOptions) *lineReader {
+ return &lineReader{
+ reader: bufio.NewReader(r),
+ keepCR: opts.KeepCR,
+ }
+}
+
// lineReader is a wrapper around a bufio.Reader that caches the next line to
// provide lookahead functionality for the next two lines.
type lineReader struct {
@@ -20,14 +27,20 @@ type lineReader struct {
cachedNextLine []byte
cachedNextLineErr error
+
+ keepCR bool
+}
+
+func (l *lineReader) ensureCachedNextLine() {
+ if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
+ l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader, l.keepCR)
+ }
}
// readLine returns the next unconsumed line and advances the internal cache of
// the lineReader.
func (l *lineReader) readLine() ([]byte, error) {
- if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
- }
+ l.ensureCachedNextLine()
if l.cachedNextLineErr != nil {
return nil, l.cachedNextLineErr
@@ -35,7 +48,7 @@ func (l *lineReader) readLine() ([]byte, error) {
next := l.cachedNextLine
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
+ l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader, l.keepCR)
return next, nil
}
@@ -46,9 +59,7 @@ func (l *lineReader) readLine() ([]byte, error) {
// io.EOF and bufio.ErrBufferFull errors are ignored so that the function can
// be used when at the end of the file.
func (l *lineReader) nextLineStartsWith(prefix string) (bool, error) {
- if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
- }
+ l.ensureCachedNextLine()
return l.lineHasPrefix(l.cachedNextLine, prefix, l.cachedNextLineErr)
}
@@ -58,14 +69,8 @@ func (l *lineReader) nextLineStartsWith(prefix string) (bool, error) {
//
// io.EOF and bufio.ErrBufferFull errors are ignored so that the function can
// be used when at the end of the file.
-//
-// The lineReader MUST be initialized by calling readLine at least once before
-// calling nextLineStartsWith. Otherwise ErrLineReaderUninitialized will be
-// returned.
func (l *lineReader) nextNextLineStartsWith(prefix string) (bool, error) {
- if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
- }
+ l.ensureCachedNextLine()
next, err := l.reader.Peek(len(prefix))
return l.lineHasPrefix(next, prefix, err)
@@ -93,22 +98,21 @@ func (l *lineReader) lineHasPrefix(line []byte, prefix string, readErr error) (b
// the next line in the Reader with the trailing newline stripped. It will return an
// io.EOF error when there is nothing left to read (at the start of the function call). It
// will return any other errors it receives from the underlying call to ReadBytes.
-func readLine(r *bufio.Reader) ([]byte, error) {
- line_, err := r.ReadBytes('\n')
- if err == io.EOF {
- if len(line_) == 0 {
- return nil, io.EOF
- }
-
- // ReadBytes returned io.EOF, because it didn't find another newline, but there is
- // still the remainder of the file to return as a line.
- line := line_
- return line, nil
- } else if err != nil {
+func readLine(r *bufio.Reader, keepCR bool) ([]byte, error) {
+ line, err := r.ReadBytes('\n')
+ if err == io.EOF && len(line) == 0 {
+ return nil, io.EOF
+ }
+ if err != nil && err != io.EOF {
return nil, err
}
- line := line_[0 : len(line_)-1]
- return dropCR(line), nil
+ if line[len(line)-1] == '\n' {
+ line = line[:len(line)-1]
+ }
+ if !keepCR {
+ return dropCR(line), nil
+ }
+ return line, nil
}
// dropCR drops a terminal \r from the data.
diff --git a/vendor/github.com/sourcegraph/go-diff/diff/reverse.go b/vendor/github.com/sourcegraph/go-diff/diff/reverse.go
new file mode 100644
index 00000000..87715efb
--- /dev/null
+++ b/vendor/github.com/sourcegraph/go-diff/diff/reverse.go
@@ -0,0 +1,192 @@
+package diff
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+)
+
+// ReverseFileDiff takes a diff.FileDiff, and returns the reverse operation.
+// This is a FileDiff that undoes the edit of the original.
+func ReverseFileDiff(fd *FileDiff) (*FileDiff, error) {
+ reverse := FileDiff{
+ OrigName: fd.NewName,
+ OrigTime: fd.NewTime,
+ NewName: fd.OrigName,
+ NewTime: fd.OrigTime,
+ Extended: fd.Extended,
+ }
+ for _, hunk := range fd.Hunks {
+ invHunk, err := reverseHunk(hunk)
+ if err != nil {
+ return nil, err
+ }
+ reverse.Hunks = append(reverse.Hunks, invHunk)
+ }
+ return &reverse, nil
+}
+
+// ReverseMultiFileDiff reverses a series of FileDiffs.
+func ReverseMultiFileDiff(fds []*FileDiff) ([]*FileDiff, error) {
+ var reverse []*FileDiff
+ for _, fd := range fds {
+ r, err := ReverseFileDiff(fd)
+ if err != nil {
+ return nil, err
+ }
+ reverse = append(reverse, r)
+ }
+ return reverse, nil
+}
+
+// A subhunk represents a portion of a Hunk.Body, split into three sections.
+// It consists of zero or more context lines, followed by zero or more orig
+// lines and then zero or more new lines.
+//
+// Each line is stored WITHOUT its starting character, but with the newlines
+// included. The final entry in a section may be missing a trailing newline.
+//
+// A missing newline in orig is represented in a Hunk by OrigNoNewlineAt,
+// but is represented here as a missing newline.
+type contextLine struct {
+ body []byte
+ bare bool
+}
+
+type subhunk struct {
+ context []contextLine
+ orig [][]byte
+ new [][]byte
+}
+
+// reverseHunk converts a Hunk into its reverse operation.
+func reverseHunk(forward *Hunk) (*Hunk, error) {
+ reverse := Hunk{
+ OrigStartLine: forward.NewStartLine,
+ OrigLines: forward.NewLines,
+ OrigNoNewlineAt: 0, // we may change this below
+ NewStartLine: forward.OrigStartLine,
+ NewLines: forward.OrigLines,
+ Section: forward.Section,
+ StartPosition: forward.StartPosition,
+ }
+ subs, err := toSubhunks(forward)
+ if err != nil {
+ return nil, err
+ }
+ for _, sub := range subs {
+ invSub := subhunk{
+ context: sub.context,
+ orig: sub.new,
+ new: sub.orig,
+ }
+ for _, line := range invSub.context {
+ if line.bare {
+ reverse.Body = append(reverse.Body, line.body...)
+ continue
+ }
+ reverse.Body = append(reverse.Body, ' ')
+ reverse.Body = append(reverse.Body, line.body...)
+ }
+ for _, line := range invSub.orig {
+ reverse.Body = append(reverse.Body, '-')
+ reverse.Body = append(reverse.Body, line...)
+ }
+ if len(invSub.orig) > 0 && reverse.Body[len(reverse.Body)-1] != '\n' {
+ // There was a missing newline in `orig`, which we encode in a
+ // hunk with an offset.
+ reverse.Body = append(reverse.Body, '\n')
+ reverse.OrigNoNewlineAt = int32(len(reverse.Body))
+ }
+ for _, line := range invSub.new {
+ reverse.Body = append(reverse.Body, '+')
+ reverse.Body = append(reverse.Body, line...)
+ }
+ }
+ return &reverse, nil
+}
+
+func extractContextLines(from *[]byte) []contextLine {
+ var lines []contextLine
+ for len(*from) > 0 {
+ if (*from)[0] == '\n' {
+ lines = append(lines, contextLine{body: []byte{'\n'}, bare: true})
+ *from = (*from)[1:]
+ continue
+ }
+ if (*from)[0] != ' ' {
+ break
+ }
+
+ newline := bytes.IndexByte(*from, '\n')
+ if newline < 0 {
+ lines = append(lines, contextLine{body: (*from)[1:]})
+ *from = nil
+ continue
+ }
+
+ lines = append(lines, contextLine{body: (*from)[1 : newline+1]})
+ *from = (*from)[newline+1:]
+ }
+ return lines
+}
+
+func extractLinesStartingWith(from *[]byte, startingWith byte) [][]byte {
+ var lines [][]byte
+ for len(*from) > 0 {
+ if (*from)[0] != startingWith {
+ break
+ }
+
+ newline := bytes.IndexByte(*from, '\n')
+ if newline < 0 {
+ lines = append(lines, (*from)[1:])
+ *from = nil
+ continue
+ }
+
+ lines = append(lines, (*from)[1:newline+1])
+ *from = (*from)[newline+1:]
+ }
+ return lines
+}
+
+// Extracts the subhunks from a diff.Hunk.
+//
+// This groups a Hunk's buffer into one or more subhunks, matching the conditions
+// of `subhunk` above. This function groups, strips prefix characters, and strips
+// a newline for `OrigNoNewlineAt` if necessary.
+func toSubhunks(hunk *Hunk) ([]subhunk, error) {
+ var body []byte = hunk.Body
+ var subhunks []subhunk
+ if len(body) == 0 {
+ return nil, nil
+ }
+ for len(body) > 0 {
+ sh := subhunk{
+ context: extractContextLines(&body),
+ orig: extractLinesStartingWith(&body, '-'),
+ new: extractLinesStartingWith(&body, '+'),
+ }
+ if len(sh.context) == 0 && len(sh.orig) == 0 && len(sh.new) == 0 {
+ // The first line didn't start with any expected prefix.
+ return nil, fmt.Errorf("unexpected character %q at start of line", body[0])
+ }
+ subhunks = append(subhunks, sh)
+ }
+ if hunk.OrigNoNewlineAt > 0 {
+ // The Hunk represents a missing newline at the end of an "orig" line with a
+ // OrigNoNewlineAt index. We represent it here as an actual missing newline.
+ var lastSubhunk *subhunk = &subhunks[len(subhunks)-1]
+ s := len(lastSubhunk.orig)
+ if s == 0 {
+ return nil, errors.New("inconsistent OrigNoNewlineAt in input")
+ }
+ var cut bool
+ lastSubhunk.orig[s-1], cut = bytes.CutSuffix(lastSubhunk.orig[s-1], []byte("\n"))
+ if !cut {
+ return nil, errors.New("missing newline in input")
+ }
+ }
+ return subhunks, nil
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go
index c592f6ad..a19a8927 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_format.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -84,7 +84,7 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar
return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
}
-// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// EqualErrorf asserts that a function returned a non-nil error (i.e. an error)
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
@@ -124,7 +124,7 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri
return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
}
-// Errorf asserts that a function returned an error (i.e. not `nil`).
+// Errorf asserts that a function returned a non-nil error (ie. an error).
//
// actualObj, err := SomeFunction()
// assert.Errorf(t, err, "error message %s", "formatted")
@@ -144,8 +144,8 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int
return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
}
-// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
-// and that the error contains the specified substring.
+// ErrorContainsf asserts that a function returned a non-nil error (i.e. an
+// error) and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
@@ -190,10 +190,10 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick
// time.Sleep(8*time.Second)
// externalValue = true
// }()
-// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
+// assert.EventuallyWithTf(t, func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "error message %s", "formatted")
func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -552,7 +552,7 @@ func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool
return NoDirExists(t, path, append([]interface{}{msg}, args...)...)
}
-// NoErrorf asserts that a function returned no error (i.e. `nil`).
+// NoErrorf asserts that a function returned a nil error (ie. no error).
//
// actualObj, err := SomeFunction()
// if assert.NoErrorf(t, err, "error message %s", "formatted") {
@@ -849,7 +849,19 @@ func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time,
return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...)
}
-// YAMLEqf asserts that two YAML strings are equivalent.
+// YAMLEqf asserts that the first documents in the two YAML strings are equivalent.
+//
+// expected := `---
+// key: value
+// ---
+// key: this is a second document, it is not evaluated
+// `
+// actual := `---
+// key: value
+// ---
+// key: this is a subsequent document, it is not evaluated
+// `
+// assert.YAMLEqf(t, expected, actual, "error message %s", "formatted")
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
index 58db9284..cd2a8606 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -146,7 +146,7 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs
return Equal(a.t, expected, actual, msgAndArgs...)
}
-// EqualError asserts that a function returned an error (i.e. not `nil`)
+// EqualError asserts that a function returned a non-nil error (i.e. an error)
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
@@ -158,7 +158,7 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...
return EqualError(a.t, theError, errString, msgAndArgs...)
}
-// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// EqualErrorf asserts that a function returned a non-nil error (i.e. an error)
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
@@ -240,7 +240,7 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string
return Equalf(a.t, expected, actual, msg, args...)
}
-// Error asserts that a function returned an error (i.e. not `nil`).
+// Error asserts that a function returned a non-nil error (ie. an error).
//
// actualObj, err := SomeFunction()
// a.Error(err)
@@ -269,8 +269,8 @@ func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ..
return ErrorAsf(a.t, err, target, msg, args...)
}
-// ErrorContains asserts that a function returned an error (i.e. not `nil`)
-// and that the error contains the specified substring.
+// ErrorContains asserts that a function returned a non-nil error (i.e. an
+// error) and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
// a.ErrorContains(err, expectedErrorSubString)
@@ -281,8 +281,8 @@ func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs .
return ErrorContains(a.t, theError, contains, msgAndArgs...)
}
-// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
-// and that the error contains the specified substring.
+// ErrorContainsf asserts that a function returned a non-nil error (i.e. an
+// error) and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
@@ -311,7 +311,7 @@ func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...inter
return ErrorIsf(a.t, err, target, msg, args...)
}
-// Errorf asserts that a function returned an error (i.e. not `nil`).
+// Errorf asserts that a function returned a non-nil error (ie. an error).
//
// actualObj, err := SomeFunction()
// a.Errorf(err, "error message %s", "formatted")
@@ -372,10 +372,10 @@ func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor
// time.Sleep(8*time.Second)
// externalValue = true
// }()
-// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
+// a.EventuallyWithTf(func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "error message %s", "formatted")
func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1096,7 +1096,7 @@ func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{})
return NoDirExistsf(a.t, path, msg, args...)
}
-// NoError asserts that a function returned no error (i.e. `nil`).
+// NoError asserts that a function returned a nil error (ie. no error).
//
// actualObj, err := SomeFunction()
// if a.NoError(err) {
@@ -1109,7 +1109,7 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
return NoError(a.t, err, msgAndArgs...)
}
-// NoErrorf asserts that a function returned no error (i.e. `nil`).
+// NoErrorf asserts that a function returned a nil error (ie. no error).
//
// actualObj, err := SomeFunction()
// if a.NoErrorf(err, "error message %s", "formatted") {
@@ -1690,7 +1690,19 @@ func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Ti
return WithinRangef(a.t, actual, start, end, msg, args...)
}
-// YAMLEq asserts that two YAML strings are equivalent.
+// YAMLEq asserts that the first documents in the two YAML strings are equivalent.
+//
+// expected := `---
+// key: value
+// ---
+// key: this is a second document, it is not evaluated
+// `
+// actual := `---
+// key: value
+// ---
+// key: this is a subsequent document, it is not evaluated
+// `
+// a.YAMLEq(expected, actual)
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1698,7 +1710,19 @@ func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interf
return YAMLEq(a.t, expected, actual, msgAndArgs...)
}
-// YAMLEqf asserts that two YAML strings are equivalent.
+// YAMLEqf asserts that the first documents in the two YAML strings are equivalent.
+//
+// expected := `---
+// key: value
+// ---
+// key: this is a second document, it is not evaluated
+// `
+// actual := `---
+// key: value
+// ---
+// key: this is a subsequent document, it is not evaluated
+// `
+// a.YAMLEqf(expected, actual, "error message %s", "formatted")
func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go
index 2fdf80fd..a44b40ed 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_order.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go
@@ -9,7 +9,7 @@ import (
func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool {
objKind := reflect.TypeOf(object).Kind()
if objKind != reflect.Slice && objKind != reflect.Array {
- return false
+ return Fail(t, fmt.Sprintf("object %T is not an ordered collection", object), msgAndArgs...)
}
objValue := reflect.ValueOf(object)
@@ -50,6 +50,9 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareR
// assert.IsIncreasing(t, []float{1, 2})
// assert.IsIncreasing(t, []string{"a", "b"})
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
return isOrdered(t, object, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
}
@@ -59,6 +62,9 @@ func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
// assert.IsNonIncreasing(t, []float{2, 1})
// assert.IsNonIncreasing(t, []string{"b", "a"})
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
return isOrdered(t, object, []compareResult{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
}
@@ -68,6 +74,9 @@ func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{})
// assert.IsDecreasing(t, []float{2, 1})
// assert.IsDecreasing(t, []string{"b", "a"})
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
return isOrdered(t, object, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
}
@@ -77,5 +86,8 @@ func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
// assert.IsNonDecreasing(t, []float{1, 2})
// assert.IsNonDecreasing(t, []string{"a", "b"})
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
return isOrdered(t, object, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
}
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
index de8de0cb..166f6372 100644
--- a/vendor/github.com/stretchr/testify/assert/assertions.go
+++ b/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -17,11 +17,10 @@ import (
"unicode"
"unicode/utf8"
- "github.com/davecgh/go-spew/spew"
- "github.com/pmezard/go-difflib/difflib"
-
- // Wrapper around gopkg.in/yaml.v3
+ // Wrapper around go.yaml.in/yaml/v3
"github.com/stretchr/testify/assert/yaml"
+ "github.com/stretchr/testify/internal/difflib"
+ "github.com/stretchr/testify/internal/spew"
)
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
@@ -33,19 +32,19 @@ type TestingT interface {
// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
// for table driven tests.
-type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool
+type ComparisonAssertionFunc = func(TestingT, interface{}, interface{}, ...interface{}) bool
// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
// for table driven tests.
-type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool
+type ValueAssertionFunc = func(TestingT, interface{}, ...interface{}) bool
// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
// for table driven tests.
-type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
+type BoolAssertionFunc = func(TestingT, bool, ...interface{}) bool
// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
// for table driven tests.
-type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
+type ErrorAssertionFunc = func(TestingT, error, ...interface{}) bool
// PanicAssertionFunc is a common function prototype when validating a panic value. Can be useful
// for table driven tests.
@@ -325,13 +324,15 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
func indentMessageLines(message string, longestLabelLen int) string {
outBuf := new(bytes.Buffer)
- for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
- // no need to align first line because it starts at the correct location (after the label)
- if i != 0 {
- // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
- outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
+ scanner := bufio.NewScanner(strings.NewReader(message))
+ for firstLine := true; scanner.Scan(); firstLine = false {
+ if !firstLine {
+ fmt.Fprint(outBuf, "\n\t"+strings.Repeat(" ", longestLabelLen+1)+"\t")
}
- outBuf.WriteString(scanner.Text())
+ fmt.Fprint(outBuf, scanner.Text())
+ }
+ if err := scanner.Err(); err != nil {
+ return fmt.Sprintf("cannot display message: %s", err)
}
return outBuf.String()
@@ -544,9 +545,8 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b
if !same {
// both are pointers but not the same type & pointing to the same address
return Fail(t, fmt.Sprintf("Not same: \n"+
- "expected: %p %#[1]v\n"+
- "actual : %p %#[2]v",
- expected, actual), msgAndArgs...)
+ "expected: %[2]s (%[1]T)(%[1]p)\n"+
+ "actual : %[4]s (%[3]T)(%[3]p)", expected, truncatingFormat("%#v", expected), actual, truncatingFormat("%#v", actual)), msgAndArgs...)
}
return true
@@ -571,8 +571,8 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
if same {
return Fail(t, fmt.Sprintf(
- "Expected and actual point to the same object: %p %#[1]v",
- expected), msgAndArgs...)
+ "Expected and actual point to the same object: %p %s",
+ expected, truncatingFormat("%#v", expected)), msgAndArgs...)
}
return true
}
@@ -604,25 +604,26 @@ func samePointers(first, second interface{}) (same bool, ok bool) {
// to a type conversion in the Go grammar.
func formatUnequalValues(expected, actual interface{}) (e string, a string) {
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
- return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)),
- fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual))
+ return fmt.Sprintf("%T(%s)", expected, truncatingFormat("%#v", expected)),
+ fmt.Sprintf("%T(%s)", actual, truncatingFormat("%#v", actual))
}
switch expected.(type) {
case time.Duration:
return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)
}
- return truncatingFormat(expected), truncatingFormat(actual)
+ return truncatingFormat("%#v", expected), truncatingFormat("%#v", actual)
}
// truncatingFormat formats the data and truncates it if it's too long.
//
// This helps keep formatted error messages lines from exceeding the
// bufio.MaxScanTokenSize max line length that the go testing framework imposes.
-func truncatingFormat(data interface{}) string {
- value := fmt.Sprintf("%#v", data)
- max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed.
- if len(value) > max {
- value = value[0:max] + "<... truncated>"
+func truncatingFormat(format string, data interface{}) string {
+ value := fmt.Sprintf(format, data)
+ // Give us space for two truncated objects and the surrounding sentence.
+ maxMessageSize := bufio.MaxScanTokenSize/2 - 100
+ if len(value) > maxMessageSize {
+ value = value[0:maxMessageSize] + "<... truncated>"
}
return value
}
@@ -743,7 +744,7 @@ func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
- return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("Expected nil, but got: %s", truncatingFormat("%#v", object)), msgAndArgs...)
}
// isEmpty gets whether the specified object is considered empty or not.
@@ -793,7 +794,7 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
- Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
+ Fail(t, fmt.Sprintf("Should be empty, but was %s", truncatingFormat("%v", object)), msgAndArgs...)
}
return pass
@@ -836,11 +837,11 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
}
l, ok := getLen(object)
if !ok {
- return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%q could not be applied builtin len()", truncatingFormat("%v", object)), msgAndArgs...)
}
if l != length {
- return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%q should have %d item(s), but has %d", truncatingFormat("%v", object), length, l), msgAndArgs...)
}
return true
}
@@ -889,7 +890,7 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{
}
if ObjectsAreEqual(expected, actual) {
- return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("Should not be: %s\n", truncatingFormat("%#v", actual)), msgAndArgs...)
}
return true
@@ -904,7 +905,7 @@ func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...inte
}
if ObjectsAreEqualValues(expected, actual) {
- return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("Should not be: %s\n", truncatingFormat("%#v", actual)), msgAndArgs...)
}
return true
@@ -964,10 +965,10 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
ok, found := containsElement(s, contains)
if !ok {
- return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%s could not be applied builtin len()", truncatingFormat("%#v", s)), msgAndArgs...)
}
if !found {
- return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%s does not contain %#v", truncatingFormat("%#v", s), contains), msgAndArgs...)
}
return true
@@ -986,10 +987,10 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
ok, found := containsElement(s, contains)
if !ok {
- return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%s could not be applied builtin len()", truncatingFormat("%#v", s)), msgAndArgs...)
}
if found {
- return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%s should not contain %#v", truncatingFormat("%#v", s), contains), msgAndArgs...)
}
return true
@@ -1031,10 +1032,10 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
av := actualMap.MapIndex(k)
if !av.IsValid() {
- return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%s does not contain %s", truncatingFormat("%#v", list), truncatingFormat("%#v", subset)), msgAndArgs...)
}
if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
- return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%s does not contain %s", truncatingFormat("%#v", list), truncatingFormat("%#v", subset)), msgAndArgs...)
}
}
@@ -1056,7 +1057,7 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...)
}
if !found {
- return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%s does not contain %#v", truncatingFormat("%#v", list), element), msgAndArgs...)
}
}
@@ -1082,12 +1083,12 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
listKind := reflect.TypeOf(list).Kind()
if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
- return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%#v has an unsupported type %s", list, listKind), msgAndArgs...)
}
subsetKind := reflect.TypeOf(subset).Kind()
if subsetKind != reflect.Array && subsetKind != reflect.Slice && subsetKind != reflect.Map {
- return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%#v has an unsupported type %s", subset, subsetKind), msgAndArgs...)
}
if subsetKind == reflect.Map && listKind == reflect.Map {
@@ -1106,7 +1107,7 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
}
}
- return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%s is a subset of %s", truncatingFormat("%#v", subset), truncatingFormat("%#v", list)), msgAndArgs...)
}
subsetList := reflect.ValueOf(subset)
@@ -1121,14 +1122,14 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
element := subsetList.Index(i).Interface()
ok, found := containsElement(list, element)
if !ok {
- return Fail(t, fmt.Sprintf("%q could not be applied builtin len()", list), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...)
}
if !found {
return true
}
}
- return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("%s is a subset of %s", truncatingFormat("%#v", subset), truncatingFormat("%#v", list)), msgAndArgs...)
}
// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
@@ -1343,9 +1344,15 @@ func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs .
if !funcDidPanic {
return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
}
- panicErr, ok := panicValue.(error)
- if !ok || panicErr.Error() != errString {
- return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...)
+ panicErr, isError := panicValue.(error)
+ if !isError || panicErr.Error() != errString {
+ msg := fmt.Sprintf("func %#v should panic with error message:\t%#v\n", f, errString)
+ if isError {
+ msg += fmt.Sprintf("\tError message:\t%#v\n", panicErr.Error())
+ }
+ msg += fmt.Sprintf("\tPanic value:\t%#v\n", panicValue)
+ msg += fmt.Sprintf("\tPanic stack:\t%s\n", panickedStack)
+ return Fail(t, msg, msgAndArgs...)
}
return true
@@ -1624,7 +1631,7 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
Errors
*/
-// NoError asserts that a function returned no error (i.e. `nil`).
+// NoError asserts that a function returned a nil error (ie. no error).
//
// actualObj, err := SomeFunction()
// if assert.NoError(t, err) {
@@ -1635,13 +1642,13 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
- return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("Received unexpected error:\n%s", truncatingFormat("%+v", err)), msgAndArgs...)
}
return true
}
-// Error asserts that a function returned an error (i.e. not `nil`).
+// Error asserts that a function returned a non-nil error (ie. an error).
//
// actualObj, err := SomeFunction()
// assert.Error(t, err)
@@ -1656,7 +1663,7 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
return true
}
-// EqualError asserts that a function returned an error (i.e. not `nil`)
+// EqualError asserts that a function returned a non-nil error (i.e. an error)
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
@@ -1674,13 +1681,13 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte
if expected != actual {
return Fail(t, fmt.Sprintf("Error message not equal:\n"+
"expected: %q\n"+
- "actual : %q", expected, actual), msgAndArgs...)
+ "actual : %s", expected, truncatingFormat("%q", actual)), msgAndArgs...)
}
return true
}
-// ErrorContains asserts that a function returned an error (i.e. not `nil`)
-// and that the error contains the specified substring.
+// ErrorContains asserts that a function returned a non-nil error (i.e. an
+// error) and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
// assert.ErrorContains(t, err, expectedErrorSubString)
@@ -1694,7 +1701,7 @@ func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...in
actual := theError.Error()
if !strings.Contains(actual, contains) {
- return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("Error %s does not contain %#v", truncatingFormat("%#v", actual), contains), msgAndArgs...)
}
return true
@@ -1760,7 +1767,7 @@ func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
h.Helper()
}
if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
- return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("Should be zero, but was %s", truncatingFormat("%v", i)), msgAndArgs...)
}
return true
}
@@ -1874,7 +1881,19 @@ func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{
return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
}
-// YAMLEq asserts that two YAML strings are equivalent.
+// YAMLEq asserts that the first documents in the two YAML strings are equivalent.
+//
+// expected := `---
+// key: value
+// ---
+// key: this is a second document, it is not evaluated
+// `
+// actual := `---
+// key: value
+// ---
+// key: this is a subsequent document, it is not evaluated
+// `
+// assert.YAMLEq(t, expected, actual)
func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -2188,8 +2207,8 @@ func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
chain := buildErrorChainString(err, false)
return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+
- "expected: %q\n"+
- "in chain: %s", expectedText, chain,
+ "expected: %s\n"+
+ "in chain: %s", truncatingFormat("%q", expectedText), truncatingFormat("%s", chain),
), msgAndArgs...)
}
@@ -2211,8 +2230,8 @@ func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
chain := buildErrorChainString(err, false)
return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
- "found: %q\n"+
- "in chain: %s", expectedText, chain,
+ "found: %s\n"+
+ "in chain: %s", truncatingFormat("%q", expectedText), truncatingFormat("%s", chain),
), msgAndArgs...)
}
@@ -2236,7 +2255,7 @@ func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{
return Fail(t, fmt.Sprintf("Should be in error chain:\n"+
"expected: %s\n"+
- "in chain: %s", expectedType, chain,
+ "in chain: %s", expectedType, truncatingFormat("%s", chain),
), msgAndArgs...)
}
@@ -2254,7 +2273,7 @@ func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interfa
return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
"found: %s\n"+
- "in chain: %s", reflect.TypeOf(target).Elem().String(), chain,
+ "in chain: %s", reflect.TypeOf(target).Elem().String(), truncatingFormat("%s", chain),
), msgAndArgs...)
}
diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go
index a0b953aa..c111589c 100644
--- a/vendor/github.com/stretchr/testify/assert/doc.go
+++ b/vendor/github.com/stretchr/testify/assert/doc.go
@@ -40,8 +40,8 @@
//
// # Assertions
//
-// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
-// All assertion functions take, as the first argument, the `*testing.T` object provided by the
+// Assertions allow you to easily write test code, and are global funcs in the assert package.
+// All assertion functions take, as the first argument, the [*testing.T] object provided by the
// testing framework. This allows the assertion funcs to write the failings and other details to
// the correct place.
//
diff --git a/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go b/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go
index 5a74c4f4..956227ca 100644
--- a/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go
+++ b/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go
@@ -7,7 +7,7 @@
// go test -tags testify_yaml_custom
//
// This implementation can be used at build time to replace the default implementation
-// to avoid linking with [gopkg.in/yaml.v3].
+// to avoid linking with [go.yaml.in/yaml/v3].
//
// In your test package:
//
diff --git a/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go b/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go
index 0bae80e3..dd89ac03 100644
--- a/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go
+++ b/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go
@@ -6,7 +6,7 @@
// indirection with an alternative implementation of this package that uses
// another implementation of YAML deserialization. This allows to not either not
// use YAML deserialization at all, or to use another implementation than
-// [gopkg.in/yaml.v3] (for example for license compatibility reasons, see [PR #1120]).
+// [go.yaml.in/yaml/v3] (for example for license compatibility reasons, see [PR #1120]).
//
// Alternative implementations are selected using build tags:
//
@@ -28,9 +28,9 @@
// [PR #1120]: https://github.com/stretchr/testify/pull/1120
package yaml
-import goyaml "gopkg.in/yaml.v3"
+import goyaml "go.yaml.in/yaml/v3"
-// Unmarshal is just a wrapper of [gopkg.in/yaml.v3.Unmarshal].
+// Unmarshal is just a wrapper of [go.yaml.in/yaml/v3.Unmarshal].
func Unmarshal(in []byte, out interface{}) error {
return goyaml.Unmarshal(in, out)
}
diff --git a/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go b/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go
index 8041803f..a51d2792 100644
--- a/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go
+++ b/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go
@@ -3,7 +3,7 @@
// Package yaml is an implementation of YAML functions that always fail.
//
// This implementation can be used at build time to replace the default implementation
-// to avoid linking with [gopkg.in/yaml.v3]:
+// to avoid linking with [go.yaml.in/yaml/v3]:
//
// go test -tags testify_yaml_fail
package yaml
diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/stretchr/testify/internal/difflib/LICENSE
similarity index 95%
rename from vendor/github.com/pmezard/go-difflib/LICENSE
rename to vendor/github.com/stretchr/testify/internal/difflib/LICENSE
index c67dad61..485be13c 100644
--- a/vendor/github.com/pmezard/go-difflib/LICENSE
+++ b/vendor/github.com/stretchr/testify/internal/difflib/LICENSE
@@ -24,4 +24,4 @@ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/stretchr/testify/internal/difflib/difflib.go
similarity index 77%
rename from vendor/github.com/pmezard/go-difflib/difflib/difflib.go
rename to vendor/github.com/stretchr/testify/internal/difflib/difflib.go
index 003e99fa..9984599b 100644
--- a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go
+++ b/vendor/github.com/stretchr/testify/internal/difflib/difflib.go
@@ -8,11 +8,14 @@
//
// - unified_diff
//
-// - context_diff
-//
// Getting unified diffs was the main goal of the port. Keep in mind this code
// is mostly suitable to output text differences in a human friendly way, there
// are no guarantees generated diffs are consumable by patch(1).
+//
+// This package was adopted from [github.com/pmezard/go-difflib] which
+// is no longer maintained.
+//
+// [github.com/pmezard/go-difflib]: https://github.com/pmezard/go-difflib
package difflib
import (
@@ -37,13 +40,6 @@ func max(a, b int) int {
return b
}
-func calculateRatio(matches, length int) float64 {
- if length > 0 {
- return 2.0 * float64(matches) / float64(length)
- }
- return 1.0
-}
-
type Match struct {
A int
B int
@@ -103,14 +99,6 @@ func NewMatcher(a, b []string) *SequenceMatcher {
return &m
}
-func NewMatcherWithJunk(a, b []string, autoJunk bool,
- isJunk func(string) bool) *SequenceMatcher {
-
- m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk}
- m.SetSeqs(a, b)
- return &m
-}
-
// Set two sequences to be compared.
func (m *SequenceMatcher) SetSeqs(a, b []string) {
m.SetSeq1(a)
@@ -199,12 +187,15 @@ func (m *SequenceMatcher) isBJunk(s string) bool {
// If IsJunk is not defined:
//
// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
-// alo <= i <= i+k <= ahi
-// blo <= j <= j+k <= bhi
+//
+// alo <= i <= i+k <= ahi
+// blo <= j <= j+k <= bhi
+//
// and for all (i',j',k') meeting those conditions,
-// k >= k'
-// i <= i'
-// and if i == i', j <= j'
+//
+// k >= k'
+// i <= i'
+// and if i == i', j <= j'
//
// In other words, of all maximal matching blocks, return one that
// starts earliest in a, and of all those maximal matching blocks that
@@ -451,66 +442,6 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
return groups
}
-// Return a measure of the sequences' similarity (float in [0,1]).
-//
-// Where T is the total number of elements in both sequences, and
-// M is the number of matches, this is 2.0*M / T.
-// Note that this is 1 if the sequences are identical, and 0 if
-// they have nothing in common.
-//
-// .Ratio() is expensive to compute if you haven't already computed
-// .GetMatchingBlocks() or .GetOpCodes(), in which case you may
-// want to try .QuickRatio() or .RealQuickRation() first to get an
-// upper bound.
-func (m *SequenceMatcher) Ratio() float64 {
- matches := 0
- for _, m := range m.GetMatchingBlocks() {
- matches += m.Size
- }
- return calculateRatio(matches, len(m.a)+len(m.b))
-}
-
-// Return an upper bound on ratio() relatively quickly.
-//
-// This isn't defined beyond that it is an upper bound on .Ratio(), and
-// is faster to compute.
-func (m *SequenceMatcher) QuickRatio() float64 {
- // viewing a and b as multisets, set matches to the cardinality
- // of their intersection; this counts the number of matches
- // without regard to order, so is clearly an upper bound
- if m.fullBCount == nil {
- m.fullBCount = map[string]int{}
- for _, s := range m.b {
- m.fullBCount[s] = m.fullBCount[s] + 1
- }
- }
-
- // avail[x] is the number of times x appears in 'b' less the
- // number of times we've seen it in 'a' so far ... kinda
- avail := map[string]int{}
- matches := 0
- for _, s := range m.a {
- n, ok := avail[s]
- if !ok {
- n = m.fullBCount[s]
- }
- avail[s] = n - 1
- if n > 0 {
- matches += 1
- }
- }
- return calculateRatio(matches, len(m.a)+len(m.b))
-}
-
-// Return an upper bound on ratio() very quickly.
-//
-// This isn't defined beyond that it is an upper bound on .Ratio(), and
-// is faster to compute than either .Ratio() or .QuickRatio().
-func (m *SequenceMatcher) RealQuickRatio() float64 {
- la, lb := len(m.a), len(m.b)
- return calculateRatio(min(la, lb), la+lb)
-}
-
// Convert range to the "ed" format
func formatRangeUnified(start, stop int) string {
// Per the diff spec at http://www.unix.org/single_unix_specification/
@@ -652,117 +583,6 @@ func formatRangeContext(start, stop int) string {
return fmt.Sprintf("%d,%d", beginning, beginning+length-1)
}
-type ContextDiff UnifiedDiff
-
-// Compare two sequences of lines; generate the delta as a context diff.
-//
-// Context diffs are a compact way of showing line changes and a few
-// lines of context. The number of context lines is set by diff.Context
-// which defaults to three.
-//
-// By default, the diff control lines (those with *** or ---) are
-// created with a trailing newline.
-//
-// For inputs that do not have trailing newlines, set the diff.Eol
-// argument to "" so that the output will be uniformly newline free.
-//
-// The context diff format normally has a header for filenames and
-// modification times. Any or all of these may be specified using
-// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate.
-// The modification times are normally expressed in the ISO 8601 format.
-// If not specified, the strings default to blanks.
-func WriteContextDiff(writer io.Writer, diff ContextDiff) error {
- buf := bufio.NewWriter(writer)
- defer buf.Flush()
- var diffErr error
- wf := func(format string, args ...interface{}) {
- _, err := buf.WriteString(fmt.Sprintf(format, args...))
- if diffErr == nil && err != nil {
- diffErr = err
- }
- }
- ws := func(s string) {
- _, err := buf.WriteString(s)
- if diffErr == nil && err != nil {
- diffErr = err
- }
- }
-
- if len(diff.Eol) == 0 {
- diff.Eol = "\n"
- }
-
- prefix := map[byte]string{
- 'i': "+ ",
- 'd': "- ",
- 'r': "! ",
- 'e': " ",
- }
-
- started := false
- m := NewMatcher(diff.A, diff.B)
- for _, g := range m.GetGroupedOpCodes(diff.Context) {
- if !started {
- started = true
- fromDate := ""
- if len(diff.FromDate) > 0 {
- fromDate = "\t" + diff.FromDate
- }
- toDate := ""
- if len(diff.ToDate) > 0 {
- toDate = "\t" + diff.ToDate
- }
- if diff.FromFile != "" || diff.ToFile != "" {
- wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol)
- wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol)
- }
- }
-
- first, last := g[0], g[len(g)-1]
- ws("***************" + diff.Eol)
-
- range1 := formatRangeContext(first.I1, last.I2)
- wf("*** %s ****%s", range1, diff.Eol)
- for _, c := range g {
- if c.Tag == 'r' || c.Tag == 'd' {
- for _, cc := range g {
- if cc.Tag == 'i' {
- continue
- }
- for _, line := range diff.A[cc.I1:cc.I2] {
- ws(prefix[cc.Tag] + line)
- }
- }
- break
- }
- }
-
- range2 := formatRangeContext(first.J1, last.J2)
- wf("--- %s ----%s", range2, diff.Eol)
- for _, c := range g {
- if c.Tag == 'r' || c.Tag == 'i' {
- for _, cc := range g {
- if cc.Tag == 'd' {
- continue
- }
- for _, line := range diff.B[cc.J1:cc.J2] {
- ws(prefix[cc.Tag] + line)
- }
- }
- break
- }
- }
- }
- return diffErr
-}
-
-// Like WriteContextDiff but returns the diff a string.
-func GetContextDiffString(diff ContextDiff) (string, error) {
- w := &bytes.Buffer{}
- err := WriteContextDiff(w, diff)
- return string(w.Bytes()), err
-}
-
// Split a string on "\n" while preserving them. The output can be used
// as input for UnifiedDiff and ContextDiff structures.
func SplitLines(s string) []string {
diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/stretchr/testify/internal/spew/LICENSE
similarity index 100%
rename from vendor/github.com/davecgh/go-spew/LICENSE
rename to vendor/github.com/stretchr/testify/internal/spew/LICENSE
diff --git a/vendor/github.com/stretchr/testify/internal/spew/README.md b/vendor/github.com/stretchr/testify/internal/spew/README.md
new file mode 100644
index 00000000..51a909e2
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/internal/spew/README.md
@@ -0,0 +1,12 @@
+go-spew
+=======
+
+[](http://copyfree.org)
+
+Go-spew implements a deep pretty printer for Go data structures to aid in
+debugging. A comprehensive suite of tests with 100% test coverage is provided
+to ensure proper functionality.
+
+## License
+
+Go-spew is licensed under the [copyfree](http://copyfree.org) ISC License.
diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/stretchr/testify/internal/spew/bypass.go
similarity index 98%
rename from vendor/github.com/davecgh/go-spew/spew/bypass.go
rename to vendor/github.com/stretchr/testify/internal/spew/bypass.go
index 79299478..70ddeaad 100644
--- a/vendor/github.com/davecgh/go-spew/spew/bypass.go
+++ b/vendor/github.com/stretchr/testify/internal/spew/bypass.go
@@ -18,6 +18,7 @@
// tag is deprecated and thus should not be used.
// Go versions prior to 1.4 are disabled because they use a different layout
// for interfaces which make the implementation of unsafeReflectValue more complex.
+//go:build !js && !appengine && !safe && !disableunsafe && go1.4
// +build !js,!appengine,!safe,!disableunsafe,go1.4
package spew
diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/stretchr/testify/internal/spew/bypasssafe.go
similarity index 96%
rename from vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
rename to vendor/github.com/stretchr/testify/internal/spew/bypasssafe.go
index 205c28d6..5e2d890d 100644
--- a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
+++ b/vendor/github.com/stretchr/testify/internal/spew/bypasssafe.go
@@ -16,6 +16,7 @@
// when the code is running on Google App Engine, compiled by GopherJS, or
// "-tags safe" is added to the go build command line. The "disableunsafe"
// tag is deprecated and thus should not be used.
+//go:build js || appengine || safe || disableunsafe || !go1.4
// +build js appengine safe disableunsafe !go1.4
package spew
diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/stretchr/testify/internal/spew/common.go
similarity index 100%
rename from vendor/github.com/davecgh/go-spew/spew/common.go
rename to vendor/github.com/stretchr/testify/internal/spew/common.go
diff --git a/vendor/github.com/davecgh/go-spew/spew/config.go b/vendor/github.com/stretchr/testify/internal/spew/config.go
similarity index 95%
rename from vendor/github.com/davecgh/go-spew/spew/config.go
rename to vendor/github.com/stretchr/testify/internal/spew/config.go
index 2e3d22f3..161895fc 100644
--- a/vendor/github.com/davecgh/go-spew/spew/config.go
+++ b/vendor/github.com/stretchr/testify/internal/spew/config.go
@@ -254,15 +254,15 @@ pointer addresses used to indirect to the final value. It provides the
following features over the built-in printing facilities provided by the fmt
package:
- * Pointers are dereferenced and followed
- * Circular data structures are detected and handled properly
- * Custom Stringer/error interfaces are optionally invoked, including
- on unexported types
- * Custom types which only implement the Stringer/error interfaces via
- a pointer receiver are optionally invoked when passing non-pointer
- variables
- * Byte arrays and slices are dumped like the hexdump -C command which
- includes offsets, byte values in hex, and ASCII output
+ - Pointers are dereferenced and followed
+ - Circular data structures are detected and handled properly
+ - Custom Stringer/error interfaces are optionally invoked, including
+ on unexported types
+ - Custom types which only implement the Stringer/error interfaces via
+ a pointer receiver are optionally invoked when passing non-pointer
+ variables
+ - Byte arrays and slices are dumped like the hexdump -C command which
+ includes offsets, byte values in hex, and ASCII output
The configuration options are controlled by modifying the public members
of c. See ConfigState for options documentation.
@@ -295,12 +295,12 @@ func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{})
// NewDefaultConfig returns a ConfigState with the following default settings.
//
-// Indent: " "
-// MaxDepth: 0
-// DisableMethods: false
-// DisablePointerMethods: false
-// ContinueOnMethod: false
-// SortKeys: false
+// Indent: " "
+// MaxDepth: 0
+// DisableMethods: false
+// DisablePointerMethods: false
+// ContinueOnMethod: false
+// SortKeys: false
func NewDefaultConfig() *ConfigState {
return &ConfigState{Indent: " "}
}
diff --git a/vendor/github.com/davecgh/go-spew/spew/doc.go b/vendor/github.com/stretchr/testify/internal/spew/doc.go
similarity index 65%
rename from vendor/github.com/davecgh/go-spew/spew/doc.go
rename to vendor/github.com/stretchr/testify/internal/spew/doc.go
index aacaac6f..722e9aa7 100644
--- a/vendor/github.com/davecgh/go-spew/spew/doc.go
+++ b/vendor/github.com/stretchr/testify/internal/spew/doc.go
@@ -21,35 +21,36 @@ debugging.
A quick overview of the additional features spew provides over the built-in
printing facilities for Go data types are as follows:
- * Pointers are dereferenced and followed
- * Circular data structures are detected and handled properly
- * Custom Stringer/error interfaces are optionally invoked, including
- on unexported types
- * Custom types which only implement the Stringer/error interfaces via
- a pointer receiver are optionally invoked when passing non-pointer
- variables
- * Byte arrays and slices are dumped like the hexdump -C command which
- includes offsets, byte values in hex, and ASCII output (only when using
- Dump style)
+ - Pointers are dereferenced and followed
+ - Circular data structures are detected and handled properly
+ - Custom Stringer/error interfaces are optionally invoked, including
+ on unexported types
+ - Custom types which only implement the Stringer/error interfaces via
+ a pointer receiver are optionally invoked when passing non-pointer
+ variables
+ - Byte arrays and slices are dumped like the hexdump -C command which
+ includes offsets, byte values in hex, and ASCII output (only when using
+ Dump style)
There are two different approaches spew allows for dumping Go data structures:
- * Dump style which prints with newlines, customizable indentation,
- and additional debug information such as types and all pointer addresses
- used to indirect to the final value
- * A custom Formatter interface that integrates cleanly with the standard fmt
- package and replaces %v, %+v, %#v, and %#+v to provide inline printing
- similar to the default %v while providing the additional functionality
- outlined above and passing unsupported format verbs such as %x and %q
- along to fmt
+ - Dump style which prints with newlines, customizable indentation,
+ and additional debug information such as types and all pointer addresses
+ used to indirect to the final value
+ - A custom Formatter interface that integrates cleanly with the standard fmt
+ package and replaces %v, %+v, %#v, and %#+v to provide inline printing
+ similar to the default %v while providing the additional functionality
+ outlined above and passing unsupported format verbs such as %x and %q
+ along to fmt
-Quick Start
+# Quick Start
This section demonstrates how to quickly get started with spew. See the
sections below for further details on formatting and configuration options.
To dump a variable with full newlines, indentation, type, and pointer
information use Dump, Fdump, or Sdump:
+
spew.Dump(myVar1, myVar2, ...)
spew.Fdump(someWriter, myVar1, myVar2, ...)
str := spew.Sdump(myVar1, myVar2, ...)
@@ -58,12 +59,13 @@ Alternatively, if you would prefer to use format strings with a compacted inline
printing style, use the convenience wrappers Printf, Fprintf, etc with
%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
%#+v (adds types and pointer addresses):
+
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
-Configuration Options
+# Configuration Options
Configuration of spew is handled by fields in the ConfigState type. For
convenience, all of the top-level functions use a global state available
@@ -74,51 +76,52 @@ equivalent to the top-level functions. This allows concurrent configuration
options. See the ConfigState documentation for more details.
The following configuration options are available:
- * Indent
- String to use for each indentation level for Dump functions.
- It is a single space by default. A popular alternative is "\t".
-
- * MaxDepth
- Maximum number of levels to descend into nested data structures.
- There is no limit by default.
-
- * DisableMethods
- Disables invocation of error and Stringer interface methods.
- Method invocation is enabled by default.
-
- * DisablePointerMethods
- Disables invocation of error and Stringer interface methods on types
- which only accept pointer receivers from non-pointer variables.
- Pointer method invocation is enabled by default.
-
- * DisablePointerAddresses
- DisablePointerAddresses specifies whether to disable the printing of
- pointer addresses. This is useful when diffing data structures in tests.
-
- * DisableCapacities
- DisableCapacities specifies whether to disable the printing of
- capacities for arrays, slices, maps and channels. This is useful when
- diffing data structures in tests.
-
- * ContinueOnMethod
- Enables recursion into types after invoking error and Stringer interface
- methods. Recursion after method invocation is disabled by default.
-
- * SortKeys
- Specifies map keys should be sorted before being printed. Use
- this to have a more deterministic, diffable output. Note that
- only native types (bool, int, uint, floats, uintptr and string)
- and types which implement error or Stringer interfaces are
- supported with other types sorted according to the
- reflect.Value.String() output which guarantees display
- stability. Natural map order is used by default.
-
- * SpewKeys
- Specifies that, as a last resort attempt, map keys should be
- spewed to strings and sorted by those strings. This is only
- considered if SortKeys is true.
-
-Dump Usage
+
+ - Indent
+ String to use for each indentation level for Dump functions.
+ It is a single space by default. A popular alternative is "\t".
+
+ - MaxDepth
+ Maximum number of levels to descend into nested data structures.
+ There is no limit by default.
+
+ - DisableMethods
+ Disables invocation of error and Stringer interface methods.
+ Method invocation is enabled by default.
+
+ - DisablePointerMethods
+ Disables invocation of error and Stringer interface methods on types
+ which only accept pointer receivers from non-pointer variables.
+ Pointer method invocation is enabled by default.
+
+ - DisablePointerAddresses
+ DisablePointerAddresses specifies whether to disable the printing of
+ pointer addresses. This is useful when diffing data structures in tests.
+
+ - DisableCapacities
+ DisableCapacities specifies whether to disable the printing of
+ capacities for arrays, slices, maps and channels. This is useful when
+ diffing data structures in tests.
+
+ - ContinueOnMethod
+ Enables recursion into types after invoking error and Stringer interface
+ methods. Recursion after method invocation is disabled by default.
+
+ - SortKeys
+ Specifies map keys should be sorted before being printed. Use
+ this to have a more deterministic, diffable output. Note that
+ only native types (bool, int, uint, floats, uintptr and string)
+ and types which implement error or Stringer interfaces are
+ supported with other types sorted according to the
+ reflect.Value.String() output which guarantees display
+ stability. Natural map order is used by default.
+
+ - SpewKeys
+ Specifies that, as a last resort attempt, map keys should be
+ spewed to strings and sorted by those strings. This is only
+ considered if SortKeys is true.
+
+# Dump Usage
Simply call spew.Dump with a list of variables you want to dump:
@@ -133,7 +136,7 @@ A third option is to call spew.Sdump to get the formatted output as a string:
str := spew.Sdump(myVar1, myVar2, ...)
-Sample Dump Output
+# Sample Dump Output
See the Dump example for details on the setup of the types and variables being
shown here.
@@ -150,13 +153,14 @@ shown here.
Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
command as shown.
+
([]uint8) (len=32 cap=32) {
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
00000020 31 32 |12|
}
-Custom Formatter
+# Custom Formatter
Spew provides a custom formatter that implements the fmt.Formatter interface
so that it integrates cleanly with standard fmt package printing functions. The
@@ -170,7 +174,7 @@ standard fmt package for formatting. In addition, the custom formatter ignores
the width and precision arguments (however they will still work on the format
specifiers not handled by the custom formatter).
-Custom Formatter Usage
+# Custom Formatter Usage
The simplest way to make use of the spew custom formatter is to call one of the
convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
@@ -184,15 +188,17 @@ functions have syntax you are most likely already familiar with:
See the Index for the full list convenience functions.
-Sample Formatter Output
+# Sample Formatter Output
Double pointer to a uint8:
+
%v: <**>5
%+v: <**>(0xf8400420d0->0xf8400420c8)5
%#v: (**uint8)5
%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
Pointer to circular struct with a uint8 field and a pointer to itself:
+
%v: <*>{1 <*>}
%+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)}
%#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)}
@@ -201,7 +207,7 @@ Pointer to circular struct with a uint8 field and a pointer to itself:
See the Printf example for details on the setup of variables being shown
here.
-Errors
+# Errors
Since it is possible for custom Stringer/error interfaces to panic, spew
detects them and handles them internally by printing the panic information
diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/stretchr/testify/internal/spew/dump.go
similarity index 96%
rename from vendor/github.com/davecgh/go-spew/spew/dump.go
rename to vendor/github.com/stretchr/testify/internal/spew/dump.go
index f78d89fc..8323041a 100644
--- a/vendor/github.com/davecgh/go-spew/spew/dump.go
+++ b/vendor/github.com/stretchr/testify/internal/spew/dump.go
@@ -488,15 +488,15 @@ pointer addresses used to indirect to the final value. It provides the
following features over the built-in printing facilities provided by the fmt
package:
- * Pointers are dereferenced and followed
- * Circular data structures are detected and handled properly
- * Custom Stringer/error interfaces are optionally invoked, including
- on unexported types
- * Custom types which only implement the Stringer/error interfaces via
- a pointer receiver are optionally invoked when passing non-pointer
- variables
- * Byte arrays and slices are dumped like the hexdump -C command which
- includes offsets, byte values in hex, and ASCII output
+ - Pointers are dereferenced and followed
+ - Circular data structures are detected and handled properly
+ - Custom Stringer/error interfaces are optionally invoked, including
+ on unexported types
+ - Custom types which only implement the Stringer/error interfaces via
+ a pointer receiver are optionally invoked when passing non-pointer
+ variables
+ - Byte arrays and slices are dumped like the hexdump -C command which
+ includes offsets, byte values in hex, and ASCII output
The configuration options are controlled by an exported package global,
spew.Config. See ConfigState for options documentation.
diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/stretchr/testify/internal/spew/format.go
similarity index 100%
rename from vendor/github.com/davecgh/go-spew/spew/format.go
rename to vendor/github.com/stretchr/testify/internal/spew/format.go
diff --git a/vendor/github.com/davecgh/go-spew/spew/spew.go b/vendor/github.com/stretchr/testify/internal/spew/spew.go
similarity index 100%
rename from vendor/github.com/davecgh/go-spew/spew/spew.go
rename to vendor/github.com/stretchr/testify/internal/spew/spew.go
diff --git a/vendor/github.com/stretchr/testify/mock/mock.go b/vendor/github.com/stretchr/testify/mock/mock.go
index efc89def..7f4d28d5 100644
--- a/vendor/github.com/stretchr/testify/mock/mock.go
+++ b/vendor/github.com/stretchr/testify/mock/mock.go
@@ -11,11 +11,11 @@ import (
"sync"
"time"
- "github.com/davecgh/go-spew/spew"
- "github.com/pmezard/go-difflib/difflib"
"github.com/stretchr/objx"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/internal/difflib"
+ "github.com/stretchr/testify/internal/spew"
)
// regex for GCCGO functions
@@ -470,7 +470,7 @@ func callString(method string, arguments Arguments, includeArgumentValues bool)
// Called tells the mock object that a method has been called, and gets an array
// of arguments to return. Panics if the call is unexpected (i.e. not preceded by
-// appropriate .On .Return() calls)
+// appropriate [Mock.On] calls)
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
func (m *Mock) Called(arguments ...interface{}) Arguments {
// get the calling function's name
@@ -493,7 +493,7 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
// MethodCalled tells the mock object that the given method has been called, and gets
// an array of arguments to return. Panics if the call is unexpected (i.e. not preceded
-// by appropriate .On .Return() calls)
+// by appropriate [Mock.On] calls)
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments {
m.mutex.Lock()
@@ -510,8 +510,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
// as the return arguments. This is because:
//
// a) this is a totally unexpected call to this method,
- // b) the arguments are not what was expected, or
- // c) the developer has forgotten to add an accompanying On...Return pair.
+ // b) the arguments are not what was expected
closestCall, mismatch := m.findClosestCall(methodName, arguments...)
m.mutex.Unlock()
@@ -595,7 +594,7 @@ type assertExpectationiser interface {
AssertExpectations(TestingT) bool
}
-// AssertExpectationsForObjects asserts that everything specified with On and Return
+// AssertExpectationsForObjects asserts that everything specified with [Mock.On]
// of the specified objects was in fact called as expected.
//
// Calls may have occurred in any order.
@@ -604,11 +603,12 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
h.Helper()
}
for _, obj := range testObjects {
- if m, ok := obj.(*Mock); ok {
- t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)")
- obj = m
+ m, ok := obj.(assertExpectationiser)
+ if !ok {
+ t.Errorf("Invalid test object type %T. Expected reference to a mock.Mock, eg: 'AssertExpectationsForObjects(t, myMock)' or 'AssertExpectationsForObjects(t, &myMock.Mock)'", obj)
+ continue
+
}
- m := obj.(assertExpectationiser)
if !m.AssertExpectations(t) {
t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m))
return false
@@ -617,7 +617,7 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
return true
}
-// AssertExpectations asserts that everything specified with On and Return was
+// AssertExpectations asserts that everything specified with [Mock.On] was
// in fact called as expected. Calls may have occurred in any order.
func (m *Mock) AssertExpectations(t TestingT) bool {
if s, ok := t.(interface{ Skipped() bool }); ok && s.Skipped() {
@@ -712,8 +712,8 @@ func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...inter
return true
}
-// IsMethodCallable checking that the method can be called
-// If the method was called more than `Repeatability` return false
+// IsMethodCallable returns true if given methodName and arguments have an
+// unsatisfied expected call registered in the Mock.
func (m *Mock) IsMethodCallable(t TestingT, methodName string, arguments ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -833,6 +833,10 @@ type IsTypeArgument struct {
// For example:
//
// args.Assert(t, IsType(""), IsType(0))
+//
+// Mock cannot match interface types because the contained type will be passed
+// to both IsType and Mock.Called, for the zero value of all interfaces this
+// will be type.
func IsType(t interface{}) *IsTypeArgument {
return &IsTypeArgument{t: reflect.TypeOf(t)}
}
@@ -1012,7 +1016,7 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
actualT := reflect.TypeOf(actual)
if actualT != expected.t {
differences++
- output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected.t.Name(), actualT.Name(), actualFmt)
+ output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, safeTypeName(expected.t), safeTypeName(actualT), actualFmt)
}
case *FunctionalOptionsArgument:
var name string
@@ -1141,6 +1145,15 @@ func (args Arguments) Bool(index int) bool {
return s
}
+// safeTypeName returns the reflect.Type's name without causing a panic.
+// If the provided reflect.Type is nil, it returns the placeholder string ""
+func safeTypeName(t reflect.Type) string {
+ if t == nil {
+ return ""
+ }
+ return t.Name()
+}
+
func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
t := reflect.TypeOf(v)
k := t.Kind()
diff --git a/vendor/github.com/stretchr/testify/require/doc.go b/vendor/github.com/stretchr/testify/require/doc.go
index c8e3f94a..ee84cc47 100644
--- a/vendor/github.com/stretchr/testify/require/doc.go
+++ b/vendor/github.com/stretchr/testify/require/doc.go
@@ -1,4 +1,4 @@
-// Package require implements the same assertions as the `assert` package but
+// Package require implements the same assertions as the assert package but
// stops test execution when a test fails.
//
// # Example Usage
@@ -21,8 +21,8 @@
//
// # Assertions
//
-// The `require` package have same global functions as in the `assert` package,
-// but instead of returning a boolean result they call `t.FailNow()`.
+// The require package have same global functions as in the assert package,
+// but instead of returning a boolean result they call [testing.T.FailNow].
// A consequence of this is that it must be called from the goroutine running
// the test function, not from other goroutines created during the test.
//
diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go
index 2d02f9bc..652871f2 100644
--- a/vendor/github.com/stretchr/testify/require/require.go
+++ b/vendor/github.com/stretchr/testify/require/require.go
@@ -180,7 +180,7 @@ func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...i
t.FailNow()
}
-// EqualError asserts that a function returned an error (i.e. not `nil`)
+// EqualError asserts that a function returned a non-nil error (i.e. an error)
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
@@ -195,7 +195,7 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte
t.FailNow()
}
-// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// EqualErrorf asserts that a function returned a non-nil error (i.e. an error)
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
@@ -295,7 +295,7 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar
t.FailNow()
}
-// Error asserts that a function returned an error (i.e. not `nil`).
+// Error asserts that a function returned a non-nil error (ie. an error).
//
// actualObj, err := SomeFunction()
// require.Error(t, err)
@@ -333,8 +333,8 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int
t.FailNow()
}
-// ErrorContains asserts that a function returned an error (i.e. not `nil`)
-// and that the error contains the specified substring.
+// ErrorContains asserts that a function returned a non-nil error (i.e. an
+// error) and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
// require.ErrorContains(t, err, expectedErrorSubString)
@@ -348,8 +348,8 @@ func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...in
t.FailNow()
}
-// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
-// and that the error contains the specified substring.
+// ErrorContainsf asserts that a function returned a non-nil error (i.e. an
+// error) and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
// require.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
@@ -387,7 +387,7 @@ func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface
t.FailNow()
}
-// Errorf asserts that a function returned an error (i.e. not `nil`).
+// Errorf asserts that a function returned a non-nil error (ie. an error).
//
// actualObj, err := SomeFunction()
// require.Errorf(t, err, "error message %s", "formatted")
@@ -429,7 +429,7 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
// time.Sleep(8*time.Second)
// externalValue = true
// }()
-// require.EventuallyWithT(t, func(c *require.CollectT) {
+// require.EventuallyWithT(t, func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// require.True(c, externalValue, "expected 'externalValue' to be true")
// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
@@ -457,10 +457,10 @@ func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitF
// time.Sleep(8*time.Second)
// externalValue = true
// }()
-// require.EventuallyWithTf(t, func(c *require.CollectT, "error message %s", "formatted") {
+// require.EventuallyWithTf(t, func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// require.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "error message %s", "formatted")
func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -671,8 +671,6 @@ func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...in
// body that contains a string.
//
// require.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -687,8 +685,6 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url s
// body that contains a string.
//
// require.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -703,8 +699,6 @@ func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url
// body that does not contain a string.
//
// require.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -719,8 +713,6 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, ur
// body that does not contain a string.
//
// require.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -734,8 +726,6 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u
// HTTPError asserts that a specified handler returns an error status code.
//
// require.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -749,8 +739,6 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string,
// HTTPErrorf asserts that a specified handler returns an error status code.
//
// require.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -764,8 +752,6 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string,
// HTTPRedirect asserts that a specified handler returns a redirect status code.
//
// require.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -779,8 +765,6 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url strin
// HTTPRedirectf asserts that a specified handler returns a redirect status code.
//
// require.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -794,8 +778,6 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
// HTTPStatusCode asserts that a specified handler returns a specified status code.
//
// require.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -809,8 +791,6 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url str
// HTTPStatusCodef asserts that a specified handler returns a specified status code.
//
// require.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -824,8 +804,6 @@ func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url st
// HTTPSuccess asserts that a specified handler returns a success status code.
//
// require.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -839,8 +817,6 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string
// HTTPSuccessf asserts that a specified handler returns a success status code.
//
// require.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
-//
-// Returns whether the assertion was successful (true) or not (false).
func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1385,12 +1361,11 @@ func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) {
t.FailNow()
}
-// NoError asserts that a function returned no error (i.e. `nil`).
+// NoError asserts that a function returned a nil error (ie. no error).
//
-// actualObj, err := SomeFunction()
-// if require.NoError(t, err) {
-// require.Equal(t, expectedObj, actualObj)
-// }
+// actualObj, err := SomeFunction()
+// require.NoError(t, err)
+// require.Equal(t, expectedObj, actualObj)
func NoError(t TestingT, err error, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1401,12 +1376,11 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) {
t.FailNow()
}
-// NoErrorf asserts that a function returned no error (i.e. `nil`).
+// NoErrorf asserts that a function returned a nil error (ie. no error).
//
-// actualObj, err := SomeFunction()
-// if require.NoErrorf(t, err, "error message %s", "formatted") {
-// require.Equal(t, expectedObj, actualObj)
-// }
+// actualObj, err := SomeFunction()
+// require.NoErrorf(t, err, "error message %s", "formatted")
+// require.Equal(t, expectedObj, actualObj)
func NoErrorf(t TestingT, err error, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1515,9 +1489,8 @@ func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg str
// NotEmpty asserts that the specified object is NOT [Empty].
//
-// if require.NotEmpty(t, obj) {
-// require.Equal(t, "two", obj[1])
-// }
+// require.NotEmpty(t, obj)
+// require.Equal(t, "two", obj[1])
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1530,9 +1503,8 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
// NotEmptyf asserts that the specified object is NOT [Empty].
//
-// if require.NotEmptyf(t, obj, "error message %s", "formatted") {
-// require.Equal(t, "two", obj[1])
-// }
+// require.NotEmptyf(t, obj, "error message %s", "formatted")
+// require.Equal(t, "two", obj[1])
func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -2135,7 +2107,19 @@ func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time,
t.FailNow()
}
-// YAMLEq asserts that two YAML strings are equivalent.
+// YAMLEq asserts that the first documents in the two YAML strings are equivalent.
+//
+// expected := `---
+// key: value
+// ---
+// key: this is a second document, it is not evaluated
+// `
+// actual := `---
+// key: value
+// ---
+// key: this is a subsequent document, it is not evaluated
+// `
+// require.YAMLEq(t, expected, actual)
func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -2146,7 +2130,19 @@ func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{
t.FailNow()
}
-// YAMLEqf asserts that two YAML strings are equivalent.
+// YAMLEqf asserts that the first documents in the two YAML strings are equivalent.
+//
+// expected := `---
+// key: value
+// ---
+// key: this is a second document, it is not evaluated
+// `
+// actual := `---
+// key: value
+// ---
+// key: this is a subsequent document, it is not evaluated
+// `
+// require.YAMLEqf(t, expected, actual, "error message %s", "formatted")
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
diff --git a/vendor/github.com/stretchr/testify/require/require.go.tmpl b/vendor/github.com/stretchr/testify/require/require.go.tmpl
index 8b328368..6a975501 100644
--- a/vendor/github.com/stretchr/testify/require/require.go.tmpl
+++ b/vendor/github.com/stretchr/testify/require/require.go.tmpl
@@ -1,4 +1,4 @@
-{{ replace .Comment "assert." "require."}}
+{{.CommentRequire}}
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
if h, ok := t.(tHelper); ok { h.Helper() }
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go
index e6f7e944..edac147e 100644
--- a/vendor/github.com/stretchr/testify/require/require_forward.go
+++ b/vendor/github.com/stretchr/testify/require/require_forward.go
@@ -147,7 +147,7 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs
Equal(a.t, expected, actual, msgAndArgs...)
}
-// EqualError asserts that a function returned an error (i.e. not `nil`)
+// EqualError asserts that a function returned a non-nil error (i.e. an error)
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
@@ -159,7 +159,7 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...
EqualError(a.t, theError, errString, msgAndArgs...)
}
-// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// EqualErrorf asserts that a function returned a non-nil error (i.e. an error)
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
@@ -241,7 +241,7 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string
Equalf(a.t, expected, actual, msg, args...)
}
-// Error asserts that a function returned an error (i.e. not `nil`).
+// Error asserts that a function returned a non-nil error (ie. an error).
//
// actualObj, err := SomeFunction()
// a.Error(err)
@@ -270,8 +270,8 @@ func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ..
ErrorAsf(a.t, err, target, msg, args...)
}
-// ErrorContains asserts that a function returned an error (i.e. not `nil`)
-// and that the error contains the specified substring.
+// ErrorContains asserts that a function returned a non-nil error (i.e. an
+// error) and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
// a.ErrorContains(err, expectedErrorSubString)
@@ -282,8 +282,8 @@ func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs .
ErrorContains(a.t, theError, contains, msgAndArgs...)
}
-// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
-// and that the error contains the specified substring.
+// ErrorContainsf asserts that a function returned a non-nil error (i.e. an
+// error) and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
@@ -312,7 +312,7 @@ func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...inter
ErrorIsf(a.t, err, target, msg, args...)
}
-// Errorf asserts that a function returned an error (i.e. not `nil`).
+// Errorf asserts that a function returned a non-nil error (ie. an error).
//
// actualObj, err := SomeFunction()
// a.Errorf(err, "error message %s", "formatted")
@@ -373,10 +373,10 @@ func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), w
// time.Sleep(8*time.Second)
// externalValue = true
// }()
-// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
+// a.EventuallyWithTf(func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "error message %s", "formatted")
func (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -539,8 +539,6 @@ func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args .
// body that contains a string.
//
// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -552,8 +550,6 @@ func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, u
// body that contains a string.
//
// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -565,8 +561,6 @@ func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string,
// body that does not contain a string.
//
// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -578,8 +572,6 @@ func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string
// body that does not contain a string.
//
// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -590,8 +582,6 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin
// HTTPError asserts that a specified handler returns an error status code.
//
// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -602,8 +592,6 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri
// HTTPErrorf asserts that a specified handler returns an error status code.
//
// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -614,8 +602,6 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str
// HTTPRedirect asserts that a specified handler returns a redirect status code.
//
// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -626,8 +612,6 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s
// HTTPRedirectf asserts that a specified handler returns a redirect status code.
//
// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -638,8 +622,6 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url
// HTTPStatusCode asserts that a specified handler returns a specified status code.
//
// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -650,8 +632,6 @@ func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url
// HTTPStatusCodef asserts that a specified handler returns a specified status code.
//
// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -662,8 +642,6 @@ func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, ur
// HTTPSuccess asserts that a specified handler returns a success status code.
//
// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -674,8 +652,6 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st
// HTTPSuccessf asserts that a specified handler returns a success status code.
//
// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
-//
-// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1097,12 +1073,11 @@ func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{})
NoDirExistsf(a.t, path, msg, args...)
}
-// NoError asserts that a function returned no error (i.e. `nil`).
+// NoError asserts that a function returned a nil error (ie. no error).
//
-// actualObj, err := SomeFunction()
-// if a.NoError(err) {
-// assert.Equal(t, expectedObj, actualObj)
-// }
+// actualObj, err := SomeFunction()
+// a.NoError(err)
+// a.Equal(expectedObj, actualObj)
func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1110,12 +1085,11 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) {
NoError(a.t, err, msgAndArgs...)
}
-// NoErrorf asserts that a function returned no error (i.e. `nil`).
+// NoErrorf asserts that a function returned a nil error (ie. no error).
//
-// actualObj, err := SomeFunction()
-// if a.NoErrorf(err, "error message %s", "formatted") {
-// assert.Equal(t, expectedObj, actualObj)
-// }
+// actualObj, err := SomeFunction()
+// a.NoErrorf(err, "error message %s", "formatted")
+// a.Equal(expectedObj, actualObj)
func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1203,9 +1177,8 @@ func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg
// NotEmpty asserts that the specified object is NOT [Empty].
//
-// if a.NotEmpty(obj) {
-// assert.Equal(t, "two", obj[1])
-// }
+// a.NotEmpty(obj)
+// a.Equal("two", obj[1])
func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1215,9 +1188,8 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) {
// NotEmptyf asserts that the specified object is NOT [Empty].
//
-// if a.NotEmptyf(obj, "error message %s", "formatted") {
-// assert.Equal(t, "two", obj[1])
-// }
+// a.NotEmptyf(obj, "error message %s", "formatted")
+// a.Equal("two", obj[1])
func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1691,7 +1663,19 @@ func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Ti
WithinRangef(a.t, actual, start, end, msg, args...)
}
-// YAMLEq asserts that two YAML strings are equivalent.
+// YAMLEq asserts that the first documents in the two YAML strings are equivalent.
+//
+// expected := `---
+// key: value
+// ---
+// key: this is a second document, it is not evaluated
+// `
+// actual := `---
+// key: value
+// ---
+// key: this is a subsequent document, it is not evaluated
+// `
+// a.YAMLEq(expected, actual)
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1699,7 +1683,19 @@ func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interf
YAMLEq(a.t, expected, actual, msgAndArgs...)
}
-// YAMLEqf asserts that two YAML strings are equivalent.
+// YAMLEqf asserts that the first documents in the two YAML strings are equivalent.
+//
+// expected := `---
+// key: value
+// ---
+// key: this is a second document, it is not evaluated
+// `
+// actual := `---
+// key: value
+// ---
+// key: this is a subsequent document, it is not evaluated
+// `
+// a.YAMLEqf(expected, actual, "error message %s", "formatted")
func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl
index 54124df1..b3b751de 100644
--- a/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl
+++ b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl
@@ -1,4 +1,4 @@
-{{.CommentWithoutT "a"}}
+{{.CommentRequireWithoutT "a"}}
func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) {
if h, ok := a.t.(tHelper); ok { h.Helper() }
{{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
diff --git a/vendor/github.com/stretchr/testify/require/requirements.go b/vendor/github.com/stretchr/testify/require/requirements.go
index 6b7ce929..375adb0a 100644
--- a/vendor/github.com/stretchr/testify/require/requirements.go
+++ b/vendor/github.com/stretchr/testify/require/requirements.go
@@ -12,18 +12,18 @@ type tHelper = interface {
// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
// for table driven tests.
-type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{})
+type ComparisonAssertionFunc = func(TestingT, interface{}, interface{}, ...interface{})
// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
// for table driven tests.
-type ValueAssertionFunc func(TestingT, interface{}, ...interface{})
+type ValueAssertionFunc = func(TestingT, interface{}, ...interface{})
// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
// for table driven tests.
-type BoolAssertionFunc func(TestingT, bool, ...interface{})
+type BoolAssertionFunc = func(TestingT, bool, ...interface{})
// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
// for table driven tests.
-type ErrorAssertionFunc func(TestingT, error, ...interface{})
+type ErrorAssertionFunc = func(TestingT, error, ...interface{})
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs"
diff --git a/vendor/github.com/tetafro/godot/.golangci.yml b/vendor/github.com/tetafro/godot/.golangci.yml
index 2b626186..9679efa7 100644
--- a/vendor/github.com/tetafro/godot/.golangci.yml
+++ b/vendor/github.com/tetafro/godot/.golangci.yml
@@ -1,9 +1,8 @@
+version: "2"
run:
concurrency: 2
- timeout: 5m
-
linters:
- disable-all: true
+ default: none
enable:
- asciicheck
- bodyclose
@@ -22,12 +21,8 @@ linters:
- gocritic
- gocyclo
- godot
- - gofmt
- - gofumpt
- - goimports
- goprintffuncname
- gosec
- - gosimple
- govet
- importas
- ineffassign
@@ -41,38 +36,39 @@ linters:
- revive
- rowserrcheck
- sqlclosecheck
- - sqlclosecheck
- staticcheck
- - stylecheck
- - typecheck
- unconvert
- unparam
- unused
- wastedassign
- whitespace
- wrapcheck
-
-linters-settings:
- godot:
- scope: toplevel
-
-issues:
- exclude-use-default: false
- exclude:
- - "do not define dynamic errors, use wrapped static errors instead"
- exclude-files:
- - ./testdata/
- exclude-rules:
- - path: _test\.go
- linters:
- - dupl
- - errcheck
- - funlen
- - gocognit
- - cyclop
- - gosec
- - noctx
- - path: main\.go
- linters:
- - cyclop
- - gomnd
+ exclusions:
+ rules:
+ - path: _test\.go
+ linters:
+ - cyclop
+ - dupl
+ - errcheck
+ - gocognit
+ - goconst
+ - gocyclo
+ - gosec
+ - noctx
+ - path: main\.go
+ linters:
+ - cyclop
+ - gocognit
+ - path: main\.go
+ text: '`defer cancel\(\)` will not run'
+ - path: (.+)\.go$
+ text: 'G404: Use of weak random number generator'
+ - path: (.+)\.go$
+ text: do not define dynamic errors, use wrapped static errors instead
+ - path: (.+)\.go$
+ text: Error return value of `.*.Body.Close` is not checked
+formatters:
+ enable:
+ - gofmt
+ - gofumpt
+ - goimports
diff --git a/vendor/github.com/tetafro/godot/.goreleaser.yml b/vendor/github.com/tetafro/godot/.goreleaser.yml
index 2f0c2466..ff599202 100644
--- a/vendor/github.com/tetafro/godot/.goreleaser.yml
+++ b/vendor/github.com/tetafro/godot/.goreleaser.yml
@@ -5,7 +5,7 @@ builds:
checksum:
name_template: checksums.txt
snapshot:
- name_template: "{{ .Tag }}"
+ version_template: "{{ .Tag }}"
changelog:
sort: asc
filters:
diff --git a/vendor/github.com/tetafro/godot/checks.go b/vendor/github.com/tetafro/godot/checks.go
index 0301fa93..13e867fb 100644
--- a/vendor/github.com/tetafro/godot/checks.go
+++ b/vendor/github.com/tetafro/godot/checks.go
@@ -111,7 +111,9 @@ func checkPeriod(c comment) *Issue {
// Get the offset of the first symbol in the last line of the comment.
// This value is used only in golangci-lint to point to the problem,
// and to replace the line when running in auto-fix mode.
- offset := c.start.Offset
+ // For inline comments, the line starts before the comment, so we
+ // subtract the column offset to get the line start.
+ offset := c.start.Offset - (c.start.Column - 1)
for i := 0; i < pos.line-1; i++ {
offset += len(c.lines[i]) + 1
}
@@ -218,7 +220,9 @@ func checkCapital(c comment) []Issue {
// Get the offset of the first symbol in the current issue's line.
// This value is used only in golangci-lint to point to the problem,
// and to replace the line when running in auto-fix mode.
- offset := c.start.Offset
+ // For inline comments, the line starts before the comment, so we
+ // subtract the column offset to get the line start.
+ offset := c.start.Offset - (c.start.Column - 1)
for i := 0; i < pos.line-1; i++ {
offset += len(c.lines[i]) + 1
}
diff --git a/vendor/github.com/tetafro/godot/file.go b/vendor/github.com/tetafro/godot/file.go
index 19b0ebe9..7b878c29 100644
--- a/vendor/github.com/tetafro/godot/file.go
+++ b/vendor/github.com/tetafro/godot/file.go
@@ -87,6 +87,8 @@ func (pf *parsedFile) getComments(scope Scope, exclude []*regexp.Regexp) []comme
// getBlockComments gets comments from the inside of top level blocks:
// var (...), const (...).
+//
+//nolint:cyclop
func (pf *parsedFile) getBlockComments(exclude []*regexp.Regexp) []comment {
var comments []comment
for _, decl := range pf.file.Decls {
@@ -109,12 +111,14 @@ func (pf *parsedFile) getBlockComments(exclude []*regexp.Regexp) []comment {
// Skip comments that are not top-level for this block
// (the block itself is top level, so comments inside this block
// would be on column 2)
- //nolint:gomnd
if pf.fset.Position(c.Pos()).Column != 2 {
continue
}
firstLine := pf.fset.Position(c.Pos()).Line
lastLine := pf.fset.Position(c.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
comments = append(comments, comment{
lines: pf.lines[firstLine-1 : lastLine],
text: getText(c, exclude),
@@ -127,7 +131,7 @@ func (pf *parsedFile) getBlockComments(exclude []*regexp.Regexp) []comment {
// getTopLevelComments gets all top level comments.
func (pf *parsedFile) getTopLevelComments(exclude []*regexp.Regexp) []comment {
- var comments []comment //nolint:prealloc
+ var comments []comment
for _, c := range pf.file.Comments {
if c == nil || len(c.List) == 0 {
continue
@@ -137,6 +141,9 @@ func (pf *parsedFile) getTopLevelComments(exclude []*regexp.Regexp) []comment {
}
firstLine := pf.fset.Position(c.Pos()).Line
lastLine := pf.fset.Position(c.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
comments = append(comments, comment{
lines: pf.lines[firstLine-1 : lastLine],
text: getText(c, exclude),
@@ -148,7 +155,7 @@ func (pf *parsedFile) getTopLevelComments(exclude []*regexp.Regexp) []comment {
// getDeclarationComments gets top level declaration comments.
func (pf *parsedFile) getDeclarationComments(exclude []*regexp.Regexp) []comment {
- var comments []comment //nolint:prealloc
+ var comments []comment
for _, decl := range pf.file.Decls {
var cg *ast.CommentGroup
switch d := decl.(type) {
@@ -164,6 +171,9 @@ func (pf *parsedFile) getDeclarationComments(exclude []*regexp.Regexp) []comment
firstLine := pf.fset.Position(cg.Pos()).Line
lastLine := pf.fset.Position(cg.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
comments = append(comments, comment{
lines: pf.lines[firstLine-1 : lastLine],
text: getText(cg, exclude),
@@ -175,13 +185,16 @@ func (pf *parsedFile) getDeclarationComments(exclude []*regexp.Regexp) []comment
// getNoInlineComments gets all except inline comments.
func (pf *parsedFile) getNoInlineComments(exclude []*regexp.Regexp) []comment {
- var comments []comment //nolint:prealloc
+ var comments []comment
for _, c := range pf.file.Comments {
if c == nil || len(c.List) == 0 {
continue
}
firstLine := pf.fset.Position(c.Pos()).Line
lastLine := pf.fset.Position(c.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
c := comment{
lines: pf.lines[firstLine-1 : lastLine],
@@ -203,13 +216,16 @@ func (pf *parsedFile) getNoInlineComments(exclude []*regexp.Regexp) []comment {
// getAllComments gets every single comment from the file.
func (pf *parsedFile) getAllComments(exclude []*regexp.Regexp) []comment {
- var comments []comment //nolint:prealloc
+ var comments []comment
for _, c := range pf.file.Comments {
if c == nil || len(c.List) == 0 {
continue
}
firstLine := pf.fset.Position(c.Pos()).Line
lastLine := pf.fset.Position(c.End()).Line
+ if firstLine < 1 || lastLine < firstLine || lastLine > len(pf.lines) {
+ continue // broken consistency, probably by the `//line` directive
+ }
comments = append(comments, comment{
lines: pf.lines[firstLine-1 : lastLine],
start: pf.fset.Position(c.List[0].Slash),
diff --git a/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go b/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go
index ae860d72..4a862521 100644
--- a/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go
+++ b/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go
@@ -16,12 +16,18 @@ import (
var Analyzer = &analysis.Analyzer{
Name: "bodyclose",
Doc: Doc,
- Run: new(runner).run,
+ Run: run,
Requires: []*analysis.Analyzer{
buildssa.Analyzer,
},
}
+func init() {
+ Analyzer.Flags.BoolVar(&checkConsumptionFlag, "check-consumption", false, "also check that response body is consumed")
+}
+
+var checkConsumptionFlag bool
+
const (
Doc = "checks whether HTTP response body is closed successfully"
@@ -30,18 +36,21 @@ const (
)
type runner struct {
- pass *analysis.Pass
- resObj types.Object
- resTyp *types.Pointer
- bodyObj types.Object
- closeMthd *types.Func
- skipFile map[*ast.File]bool
+ pass *analysis.Pass
+ resObj types.Object
+ resTyp *types.Pointer
+ bodyObj types.Object
+ closeMthd *types.Func
+ skipFile map[*ast.File]bool
+ checkConsumption bool
}
-// run executes an analysis for the pass. The receiver is passed
-// by value because this func is called in parallel for different passes.
-func (r runner) run(pass *analysis.Pass) (interface{}, error) {
- r.pass = pass
+// run executes an analysis for the pass
+func run(pass *analysis.Pass) (interface{}, error) {
+ r := runner{
+ pass: pass,
+ checkConsumption: checkConsumptionFlag,
+ }
funcs := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA).SrcFuncs
r.resObj = analysisutil.LookupFromImports(pass.Pkg.Imports(), nethttpPath, "Response")
@@ -96,7 +105,11 @@ FuncLoop:
for i := range b.Instrs {
pos := b.Instrs[i].Pos()
if r.isopen(b, i) {
- pass.Reportf(pos, "response body must be closed")
+ if r.checkConsumption {
+ pass.Reportf(pos, "response body must be closed and consumed")
+ } else {
+ pass.Reportf(pos, "response body must be closed")
+ }
}
}
}
@@ -216,11 +229,8 @@ func (r *runner) isopen(b *ssa.BasicBlock, i int) bool {
if len(*bOp.Referrers()) == 0 {
return true
}
- ccalls := *bOp.Referrers()
- for _, ccall := range ccalls {
- if r.isCloseCall(ccall) {
- return false
- }
+ if r.isBodyProperlyHandled(bOp) {
+ return false
}
}
case *ssa.Phi: // Called in the higher-level block
@@ -242,11 +252,8 @@ func (r *runner) isopen(b *ssa.BasicBlock, i int) bool {
if len(*bOp.Referrers()) == 0 {
return true
}
- ccalls := *bOp.Referrers()
- for _, ccall := range ccalls {
- if r.isCloseCall(ccall) {
- return false
- }
+ if r.isBodyProperlyHandled(bOp) {
+ return false
}
}
}
@@ -268,6 +275,7 @@ func (r *runner) getReqCall(instr ssa.Instruction) (*ssa.Call, bool) {
strings.Contains(callType, "net/http.ResponseController") {
return nil, false
}
+
return call, true
}
@@ -300,6 +308,102 @@ func (r *runner) getBodyOp(instr ssa.Instruction) (*ssa.UnOp, bool) {
return op, true
}
+// isBodyProperlyHandled checks if response body is properly handled (closed and optionally consumed based on flag)
+func (r *runner) isBodyProperlyHandled(bOp *ssa.UnOp) bool {
+ ccalls := *bOp.Referrers()
+
+ for _, ccall := range ccalls {
+ if r.isCloseCall(ccall) {
+ // Early return if consumption checking is disabled
+ if !r.checkConsumption {
+ return true
+ }
+ // Close found and consumption checking enabled - check consumption
+ return r.hasConsumptionForBody(bOp)
+ }
+ }
+
+ // No close call found
+ return false
+}
+
+// hasConsumptionForBody searches the function for consumption calls that use the specific response body
+func (r *runner) hasConsumptionForBody(bodyOp *ssa.UnOp) bool {
+ fn := bodyOp.Block().Parent()
+
+ // Search for consumption functions that specifically consume this response body
+ for _, block := range fn.Blocks {
+ for _, blockInstr := range block.Instrs {
+ if call, ok := blockInstr.(*ssa.Call); ok {
+ if r.isConsumptionFunction(call) && r.isCallUsingBody(call, bodyOp) {
+ return true
+ }
+ }
+ }
+ }
+
+ return false
+}
+
+// isCallUsingBody checks if a consumption function call uses the specific response body
+func (r *runner) isCallUsingBody(call *ssa.Call, responseBodyOp *ssa.UnOp) bool {
+ // Get the FieldAddr of the response body we're checking
+ responseBodyFieldAddr, ok := responseBodyOp.X.(*ssa.FieldAddr)
+ if !ok {
+ return false
+ }
+
+ // Check if any argument to the call refers to this specific response body
+ for _, arg := range call.Call.Args {
+ if r.isArgumentMatchingBody(arg, responseBodyFieldAddr) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// isArgumentMatchingBody checks if a function argument refers to the same response body instance
+func (r *runner) isArgumentMatchingBody(arg ssa.Value, responseBodyFieldAddr *ssa.FieldAddr) bool {
+ switch v := arg.(type) {
+ case *ssa.FieldAddr:
+ // Direct field access - check if it's accessing Body field of same response
+ return v.X == responseBodyFieldAddr.X && v.Field == responseBodyFieldAddr.Field
+ case *ssa.UnOp:
+ // Dereference of field access - check if it's dereferencing the same response body field
+ if fieldAddr, ok := v.X.(*ssa.FieldAddr); ok {
+ return fieldAddr.X == responseBodyFieldAddr.X && fieldAddr.Field == responseBodyFieldAddr.Field
+ }
+ case *ssa.ChangeInterface:
+ // Type conversion - check if it converts the response body
+ if unOp, ok := v.X.(*ssa.UnOp); ok {
+ if fieldAddr, ok := unOp.X.(*ssa.FieldAddr); ok {
+ return fieldAddr.X == responseBodyFieldAddr.X && fieldAddr.Field == responseBodyFieldAddr.Field
+ }
+ }
+ }
+ return false
+}
+
+func (r *runner) isConsumptionFunction(call *ssa.Call) bool {
+ if call.Call.StaticCallee() != nil {
+ callee := call.Call.StaticCallee()
+ if callee.Pkg != nil {
+ pkg := callee.Pkg.Pkg.Path()
+ name := callee.Name()
+
+ // Check for known consumption functions
+ if (pkg == "io" && (name == "Copy" || name == "ReadAll")) ||
+ (pkg == "io/ioutil" && name == "ReadAll") ||
+ (pkg == "encoding/json" && name == "NewDecoder") ||
+ (pkg == "bufio" && (name == "NewScanner" || name == "NewReader")) {
+ return true
+ }
+ }
+ }
+ return false
+}
+
func (r *runner) isCloseCall(ccall ssa.Instruction) bool {
switch ccall := ccall.(type) {
case *ssa.Defer:
diff --git a/vendor/github.com/uudashr/iface/identical/identical.go b/vendor/github.com/uudashr/iface/identical/identical.go
index 0f470e54..4db64238 100644
--- a/vendor/github.com/uudashr/iface/identical/identical.go
+++ b/vendor/github.com/uudashr/iface/identical/identical.go
@@ -5,7 +5,7 @@ import (
"go/ast"
"go/token"
"go/types"
- "reflect"
+ "os"
"slices"
"strings"
@@ -15,7 +15,7 @@ import (
"golang.org/x/tools/go/ast/inspector"
)
-// Analyzer is the analysis pass for detecting identical interfaces.
+// Analyzer detects interfaces within the same package that have identical methods or type constraints.
var Analyzer = newAnalyzer()
func newAnalyzer() *analysis.Analyzer {
@@ -56,46 +56,49 @@ func (r *runner) run(pass *analysis.Pass) (interface{}, error) {
}
if r.debug {
- fmt.Printf("GenDecl: %v specs=%d\n", decl.Tok, len(decl.Specs))
+ fmt.Fprintf(os.Stderr, "GenDecl: %v specs=%d\n", decl.Tok, len(decl.Specs))
}
if decl.Tok != token.TYPE {
return
}
+ if directive.ShouldIgnore(decl.Doc, pass.Analyzer.Name) {
+ return
+ }
+
for i, spec := range decl.Specs {
- if r.debug {
- fmt.Printf(" spec[%d]: %v %v\n", i, spec, reflect.TypeOf(spec))
- }
+ r.debugf(" spec[%d]: %v %T\n", i, spec, spec)
ts, ok := spec.(*ast.TypeSpec)
if !ok {
- return
+ // this code is unreachable since we already have guard the token type
+ continue
}
+ r.debugf(" -> ts.Type %T\n", ts.Type)
+
ifaceType, ok := ts.Type.(*ast.InterfaceType)
if !ok {
- return
+ continue
}
if r.debug {
- fmt.Println("Interface declaration:", ts.Name.Name, ts.Pos(), len(ifaceType.Methods.List))
+ fmt.Fprintln(os.Stderr, " -> Interface declaration:", ts.Name.Name, ts.Pos(), len(ifaceType.Methods.List))
- for i, field := range ifaceType.Methods.List {
+ for j, field := range ifaceType.Methods.List {
switch ft := field.Type.(type) {
case *ast.FuncType:
- fmt.Printf(" [%d] Field: func %s %v %v\n", i, field.Names[0].Name, reflect.TypeOf(field.Type), field.Pos())
+ fmt.Fprintf(os.Stderr, " [%d] Field: func %s %T %v\n", j, field.Names[0].Name, ft, field.Pos())
case *ast.Ident:
- fmt.Printf(" [%d] Field: iface %s %v %v\n", i, ft.Name, reflect.TypeOf(field.Type), field.Pos())
+ fmt.Fprintf(os.Stderr, " [%d] Field: iface %s %T %v\n", j, ft.Name, ft, field.Pos())
default:
- fmt.Printf(" [%d] Field: unknown %v\n", i, reflect.TypeOf(ft))
+ fmt.Fprintf(os.Stderr, " [%d] Field: unknown %T\n", j, ft)
}
}
}
- dir := directive.ParseIgnore(decl.Doc)
- if dir != nil && dir.ShouldIgnore(pass.Analyzer.Name) {
- // skip due to ignore directive
+ if directive.ShouldIgnore(ts.Doc, pass.Analyzer.Name) {
continue
}
@@ -103,12 +106,12 @@ func (r *runner) run(pass *analysis.Pass) (interface{}, error) {
obj := pass.TypesInfo.Defs[ts.Name]
if obj == nil {
- return
+ continue
}
iface, ok := obj.Type().Underlying().(*types.Interface)
if !ok {
- return
+ continue
}
ifaceTypes[ts.Name.Name] = iface
@@ -144,6 +147,12 @@ func (r *runner) run(pass *analysis.Pass) (interface{}, error) {
func (r *runner) debugln(a ...any) {
if r.debug {
- fmt.Println(a...)
+ fmt.Fprintln(os.Stderr, a...)
+ }
+}
+
+func (r *runner) debugf(format string, a ...any) {
+ if r.debug {
+ fmt.Fprintf(os.Stderr, format, a...)
}
}
diff --git a/vendor/github.com/uudashr/iface/internal/directive/directive.go b/vendor/github.com/uudashr/iface/internal/directive/directive.go
index f7c3ee34..8589f804 100644
--- a/vendor/github.com/uudashr/iface/internal/directive/directive.go
+++ b/vendor/github.com/uudashr/iface/internal/directive/directive.go
@@ -74,3 +74,12 @@ func (i *Ignore) ShouldIgnore(name string) bool {
return i.hasName(name)
}
+
+func ShouldIgnore(doc *ast.CommentGroup, name string) bool {
+ dir := ParseIgnore(doc)
+ if dir == nil {
+ return false
+ }
+
+ return dir.ShouldIgnore(name)
+}
diff --git a/vendor/github.com/uudashr/iface/opaque/opaque.go b/vendor/github.com/uudashr/iface/opaque/opaque.go
index c3cba80a..f3431ca0 100644
--- a/vendor/github.com/uudashr/iface/opaque/opaque.go
+++ b/vendor/github.com/uudashr/iface/opaque/opaque.go
@@ -3,8 +3,9 @@ package opaque
import (
"fmt"
"go/ast"
+ "go/token"
"go/types"
- "reflect"
+ "os"
"strings"
"github.com/uudashr/iface/internal/directive"
@@ -13,7 +14,7 @@ import (
"golang.org/x/tools/go/ast/inspector"
)
-// Analyzer is the analysis pass for detecting opaque interface returns.
+// Analyzer detects functions that return an interface type, but only ever return a single concrete implementation.
var Analyzer = newAnalyzer()
func newAnalyzer() *analysis.Analyzer {
@@ -49,7 +50,10 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
funcDecl := n.(*ast.FuncDecl)
if funcDecl.Recv != nil {
- // skip methods
+ // Skip methods because their return types may be dictated by interface
+ // contracts that the receiver type satisfies. Unlike standalone functions,
+ // methods are often created to fulfill an interface, so the return type
+ // is not a free design choice. Flagging these would produce false positives.
return
}
@@ -64,44 +68,56 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
}
if r.debug {
- fmt.Printf("Function declaration %s\n", funcDecl.Name.Name)
- fmt.Printf(" Results len=%d\n", len(funcDecl.Type.Results.List))
+ fmt.Fprintf(os.Stderr, "Function declaration %s\n", funcDecl.Name.Name)
+ fmt.Fprintf(os.Stderr, " Results len=%d\n", len(funcDecl.Type.Results.List))
}
- dir := directive.ParseIgnore(funcDecl.Doc)
- if dir != nil && dir.ShouldIgnore(pass.Analyzer.Name) {
- // skip ignored function
+ if directive.ShouldIgnore(funcDecl.Doc, pass.Analyzer.Name) {
return
}
- // Pre-check, only function that has interface return type will be processed
- var hasInterfaceReturnType bool
+ var (
+ hasInterfaceReturnType bool
+ outCount int
+ )
- var outCount int
+ namedReturnObjs := make(map[*types.Var]int)
+ {
+ idx := 0
- for i, result := range funcDecl.Type.Results.List {
- outInc := 1
- if namesLen := len(result.Names); namesLen > 0 {
- outInc = namesLen
- }
+ for i, result := range funcDecl.Type.Results.List {
+ if r.debug {
+ fmt.Fprintf(os.Stderr, " result[%d] %v %T names=%v\n", i, result.Type, result.Type, result.Names)
+ }
- outCount += outInc
+ for j, name := range result.Names {
+ if obj := pass.TypesInfo.Defs[name]; obj != nil {
+ r.debugf(" name[%d] %v def=%v defAddr=%p\n", j, name, obj, obj)
- resType := result.Type
- typ := pass.TypesInfo.TypeOf(resType)
+ if v, ok := obj.(*types.Var); ok {
+ namedReturnObjs[v] = idx
+ }
+ } else {
+ r.debugf(" name[%d] %v def=unknown\n", j, name)
+ }
- if r.debug {
- fmt.Printf(" [%d] len=%d %v %v %v | %v %v interface=%t\n", i, len(result.Names), result.Names, resType, reflect.TypeOf(resType), typ, reflect.TypeOf(typ), types.IsInterface(typ))
- }
+ idx++
+ }
- if types.IsInterface(typ) && !hasInterfaceReturnType {
- hasInterfaceReturnType = true
+ if len(result.Names) == 0 {
+ idx++
+ }
+
+ outCount += max(1, len(result.Names))
+
+ if !hasInterfaceReturnType {
+ typ := pass.TypesInfo.TypeOf(result.Type)
+ hasInterfaceReturnType = typ != nil && types.IsInterface(typ)
+ }
}
}
- if r.debug {
- fmt.Printf(" hasInterface=%t outCount=%d\n", hasInterfaceReturnType, outCount)
- }
+ r.debugf(" hasInterface=%t outCount=%d\n", hasInterfaceReturnType, outCount)
if !hasInterfaceReturnType {
// skip, since it has no interface return type
@@ -114,37 +130,108 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
retStmtTypes[i] = make(map[types.Type]struct{})
}
+ r.debugln(" Body")
ast.Inspect(funcDecl.Body, func(n ast.Node) bool {
switch n := n.(type) {
case *ast.FuncLit:
- // ignore nested functions
+ r.debugln(" FuncLit")
+
return false
- case *ast.ReturnStmt:
+ case *ast.AssignStmt:
+ if n.Tok != token.ASSIGN {
+ return true
+ }
+
if r.debug {
- fmt.Printf(" Return statements %v len=%d\n", n.Results, len(n.Results))
+ r.debugf(" AssignStmt token %q lhsLen=%d rhsLen=%d\n", n.Tok, len(n.Lhs), len(n.Rhs))
}
- for i, result := range n.Results {
+ for i, lhs := range n.Lhs {
+ r.debugf(" lhs[%d] %v %T\n", i, lhs, lhs)
+
+ ident, ok := lhs.(*ast.Ident)
+ if !ok {
+ continue
+ }
+
+ obj := pass.TypesInfo.Uses[ident]
+ r.debugf(" -> typeObj %v\n", obj)
+
+ if obj == nil {
+ continue
+ }
+
+ v, ok := obj.(*types.Var)
+ r.debugf(" -> types.Var=%t\n", ok)
+
+ if !ok {
+ continue
+ }
+
+ pos, found := namedReturnObjs[v]
+ r.debugf(" -> namedFound=%t\n", found)
+
+ if !found {
+ continue
+ }
+
+ var typ types.Type
+
if r.debug {
- fmt.Printf(" [%d] %v %v\n", i, result, reflect.TypeOf(result))
+ fmt.Fprintf(os.Stderr, " -> rhsLen=%d\n", len(n.Rhs))
+ }
+
+ switch {
+ case len(n.Rhs) == 1:
+ typ = pass.TypesInfo.TypeOf(n.Rhs[0])
+ if tuple, ok := typ.(*types.Tuple); ok {
+ if i < tuple.Len() {
+ typ = tuple.At(i).Type()
+ } else {
+ typ = nil
+ }
+ }
+
+ r.debugf(" -> rhs[0] typ %v %T\n", typ, typ)
+ case i < len(n.Rhs):
+ typ = pass.TypesInfo.TypeOf(n.Rhs[i])
+ r.debugf(" -> rhs[%d] typ %v %T\n", i, typ, typ)
+ default:
+ typ = nil
+
+ r.debugf(" -> rhs default\n")
+ }
+
+ if typ != nil && !isUntypedNil(typ) {
+ retStmtTypes[pos][typ] = struct{}{}
}
+ }
+
+ return true
+ case *ast.ReturnStmt:
+ if r.debug {
+ fmt.Fprintf(os.Stderr, " ReturnStmt results %v len=%d\n", n.Results, len(n.Results))
+ }
+
+ for i, result := range n.Results {
+ r.debugf(" [%d] %v %T\n", i, result, result)
switch res := result.(type) {
case *ast.CallExpr:
- if r.debug {
- fmt.Printf(" CallExpr Fun: %v %v\n", res.Fun, reflect.TypeOf(res.Fun))
- }
+ // Multi-return calls produce a Tuple; unwrap each element to
+ // record types by position. Single-value calls fall to default.
+ r.debugf(" CallExpr Fun: %v %T\n", res.Fun, res.Fun)
typ := pass.TypesInfo.TypeOf(res)
switch typ := typ.(type) {
case *types.Tuple:
- for i := range typ.Len() {
- v := typ.At(i)
+ for j := range typ.Len() {
+ v := typ.At(j)
vTyp := v.Type()
- retStmtTypes[i][vTyp] = struct{}{}
+ retStmtTypes[j][vTyp] = struct{}{}
if r.debug {
- fmt.Printf(" Tuple [%d]: %v %v | %v %v interface=%t\n", i, v, reflect.TypeOf(v), vTyp, reflect.TypeOf(vTyp), types.IsInterface(vTyp))
+ fmt.Fprintf(os.Stderr, " Tuple [%d]: %v %T | %v %T interface=%t\n", j, v, v, vTyp, vTyp, types.IsInterface(vTyp))
}
}
default:
@@ -152,36 +239,33 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
}
case *ast.Ident:
- if r.debug {
- fmt.Printf(" Ident: %v %v\n", res, reflect.TypeOf(res))
+ // Skip untyped nil — not a concrete type. All other identifiers
+ // (variables, constants, etc.) are recorded as-is.
+ r.debugf(" Ident: %v %T\n", res, res)
+
+ if obj := pass.TypesInfo.Uses[res]; obj != nil {
+ if v, ok := obj.(*types.Var); ok {
+ if _, found := namedReturnObjs[v]; found {
+ break
+ }
+ }
}
typ := pass.TypesInfo.TypeOf(res)
isNilStmt := isUntypedNil(typ)
if r.debug {
- fmt.Printf(" Ident type: %v %v interface=%t, untypedNil=%t\n", typ, reflect.TypeOf(typ), types.IsInterface(typ), isNilStmt)
+ fmt.Fprintf(os.Stderr, " Ident type: %v %T interface=%t, untypedNil=%t\n", typ, typ, types.IsInterface(typ), isNilStmt)
}
if !isNilStmt {
retStmtTypes[i][typ] = struct{}{}
}
- case *ast.UnaryExpr:
- if r.debug {
- fmt.Printf(" UnaryExpr X: %v \n", res.X)
- }
-
- typ := pass.TypesInfo.TypeOf(res)
-
- if r.debug {
- fmt.Printf(" UnaryExpr type: %v %v interface=%t\n", typ, reflect.TypeOf(typ), types.IsInterface(typ))
- }
-
- retStmtTypes[i][typ] = struct{}{}
default:
- if r.debug {
- fmt.Printf(" Unknown: %v %v\n", res, reflect.TypeOf(res))
- }
+ // Catches everything else: UnaryExpr (`&foo`), SelectorExpr,
+ // TypeAssertExpr, CompositeLit, etc. pass.TypesInfo.TypeOf(res)
+ // resolves the type correctly regardless of AST node kind.
+ r.debugf(" OtherExpr: %v %T\n", res, res)
typ := pass.TypesInfo.TypeOf(res)
retStmtTypes[i][typ] = struct{}{}
@@ -215,8 +299,10 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
continue
}
- if typ.String() == "error" {
- // very common case to have return type error
+ errorType := types.Universe.Lookup("error").Type()
+ anyType := types.Universe.Lookup("any").Type()
+
+ if types.Identical(typ, errorType) || types.Identical(typ, anyType) {
continue
}
@@ -251,7 +337,7 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
}
if r.debug {
- fmt.Printf("stmtType: %v %v | %v %v\n", stmtTyp, reflect.TypeOf(stmtTyp), stmtTyp.Underlying(), reflect.TypeOf(stmtTyp.Underlying()))
+ fmt.Fprintf(os.Stderr, "stmtType: %v %T | %v %T\n", stmtTyp, stmtTyp, stmtTyp.Underlying(), stmtTyp.Underlying())
}
switch stmtTyp := stmtTyp.(type) {
@@ -284,15 +370,15 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
stmtTypName)
pass.Report(analysis.Diagnostic{
- Pos: result.Pos(),
+ Pos: result.Type.Pos(),
Message: msg,
SuggestedFixes: []analysis.SuggestedFix{
{
Message: "Replace the interface return type with the concrete type",
TextEdits: []analysis.TextEdit{
{
- Pos: result.Pos(),
- End: result.End(),
+ Pos: result.Type.Pos(),
+ End: result.Type.End(),
NewText: []byte(stmtTypName),
},
},
@@ -341,6 +427,10 @@ func fromSamePackage(pass *analysis.Pass, typ types.Type) bool {
}
func removePkgPrefix(typeStr string) string {
+ if len(typeStr) == 0 {
+ return typeStr
+ }
+
if typeStr[0] == '*' {
return "*" + removePkgPrefix(typeStr[1:])
}
@@ -351,3 +441,15 @@ func removePkgPrefix(typeStr string) string {
return typeStr
}
+
+func (r *runner) debugf(format string, a ...any) {
+ if r.debug {
+ fmt.Fprintf(os.Stderr, format, a...)
+ }
+}
+
+func (r *runner) debugln(a ...any) {
+ if r.debug {
+ fmt.Fprintln(os.Stderr, a...)
+ }
+}
diff --git a/vendor/github.com/uudashr/iface/unexported/unexported.go b/vendor/github.com/uudashr/iface/unexported/unexported.go
index 27a31ff1..c933d1b7 100644
--- a/vendor/github.com/uudashr/iface/unexported/unexported.go
+++ b/vendor/github.com/uudashr/iface/unexported/unexported.go
@@ -4,7 +4,8 @@ import (
"fmt"
"go/ast"
"go/types"
- "reflect"
+ "os"
+ "strings"
"github.com/uudashr/iface/internal/directive"
"golang.org/x/tools/go/analysis"
@@ -21,7 +22,7 @@ func newAnalyzer() *analysis.Analyzer {
analyzer := &analysis.Analyzer{
Name: "unexported",
Doc: "Detects interfaces which are not exported but are used as parameters or return values in exported functions or methods.",
- URL: "https://pkg.go.dev/github.com/uudashr/iface/visibility",
+ URL: "https://pkg.go.dev/github.com/uudashr/iface/unexported",
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: r.run,
}
@@ -47,11 +48,7 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
r.debugln("FuncDecl:", funcDecl.Name.Name)
- dir := directive.ParseIgnore(funcDecl.Doc)
- if dir != nil && dir.ShouldIgnore(pass.Analyzer.Name) {
- // skip ignored function
- r.debugln(" skip ignored")
-
+ if directive.ShouldIgnore(funcDecl.Doc, pass.Analyzer.Name) {
return
}
@@ -62,153 +59,199 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
if r.debug {
infoType := pass.TypesInfo.TypeOf(recvType)
- fmt.Println(" recvType:", recvType, "infoType:", infoType, "reflectType:", reflect.TypeOf(recvType))
+ fmt.Fprintf(os.Stderr, " recvType: %v infoType: %v reflectType: %T\n", recvType, infoType, recvType)
}
- switch typ := recvType.(type) {
- case *ast.Ident:
- r.debugln(" recvIdent:", typ.Name)
-
- recvName = typ.Name
- case *ast.StarExpr:
- r.debugln(" recvStarExpr:", typ.X)
-
- if ident, ok := typ.X.(*ast.Ident); ok {
- r.debugln(" recvIdent:", ident.Name)
- recvName = ident.Name
- } else {
- r.debugln(" unhandled")
- }
- default:
- r.debugln(" unhandled")
+ inner := recvType
+ if star, ok := inner.(*ast.StarExpr); ok {
+ inner = star.X
}
+
+ recvName = typeName(inner)
}
if !funcDecl.Name.IsExported() {
// skip unexported functions
- r.debugln(" skip non-exported")
+ r.debugln(" skip non-exported")
return
}
- r.debugln(" params:")
+ r.debugln(" params:")
- params := funcDecl.Type.Params
+ for _, param := range funcDecl.Type.Params.List {
+ r.checkType(pass, param.Type, funcDecl, recvName, "parameter")
+ }
- for _, param := range params.List {
- paramType := param.Type
- infoType := pass.TypesInfo.TypeOf(paramType)
+ r.debugln(" results:")
- r.debugln(" paramType:", paramType, "infoType:", infoType, "reflectType:", reflect.TypeOf(paramType))
+ if funcDecl.Type.Results == nil {
+ r.debugln(" no results")
- if !types.IsInterface(infoType) {
- // skip non-interface
- r.debugln(" skip non-interface")
+ return
+ }
- continue
- }
+ for _, result := range funcDecl.Type.Results.List {
+ r.checkType(pass, result.Type, funcDecl, recvName, "return value")
+ }
+ })
- if infoType.String() == "error" {
- // skip error interface
- r.debugln(" skip error interface")
+ return nil, nil
+}
- continue
- }
+// findIdent recursively unwraps StarExpr, Ellipsis, and ArrayType to locate the innermost
+// *ast.Ident or *ast.SelectorExpr. Returns nil if not found.
+func findIdent(expr ast.Expr) ast.Expr {
+ for {
+ switch e := expr.(type) {
+ case *ast.StarExpr:
+ expr = e.X
+ case *ast.Ellipsis:
+ expr = e.Elt
+ case *ast.ArrayType:
+ expr = e.Elt
+ case *ast.IndexExpr:
+ expr = e.X
+ case *ast.IndexListExpr:
+ expr = e.X
+ case *ast.ChanType:
+ expr = e.Value
+ case *ast.MapType:
+ expr = e.Value
+ case *ast.Ident, *ast.SelectorExpr:
+ return e
+ default:
+ return nil
+ }
+ }
+}
- if infoType.String() == "any" {
- // skip any interface
- r.debugln(" skip any interface")
+// typeName reconstructs the type string as written in source from an AST expression.
+func typeName(expr ast.Expr) string {
+ switch e := expr.(type) {
+ case *ast.ArrayType:
+ if e.Len == nil {
+ return "[]" + typeName(e.Elt)
+ }
- continue
+ return "[" + typeName(e.Len) + "]" + typeName(e.Elt)
+ case *ast.BasicLit:
+ return e.Value
+ case *ast.Ident:
+ return e.Name
+ case *ast.StarExpr:
+ return "*" + typeName(e.X)
+ case *ast.Ellipsis:
+ return "..." + typeName(e.Elt)
+ case *ast.ChanType:
+ switch e.Dir {
+ case ast.SEND:
+ return "chan<- " + typeName(e.Value)
+ case ast.RECV:
+ return "<-chan " + typeName(e.Value)
+ default:
+ return "chan " + typeName(e.Value)
+ }
+ case *ast.MapType:
+ return "map[" + typeName(e.Key) + "]" + typeName(e.Value)
+ case *ast.SelectorExpr:
+ return typeName(e.X) + "." + e.Sel.Name
+ case *ast.IndexExpr:
+ return typeName(e.X) + "[" + typeName(e.Index) + "]"
+ case *ast.IndexListExpr:
+ var b strings.Builder
+ b.WriteString(typeName(e.X))
+ b.WriteByte('[')
+
+ for i, idx := range e.Indices {
+ if i > 0 {
+ b.WriteString(", ")
}
- switch typ := paramType.(type) {
- case *ast.Ident:
- if !typ.IsExported() {
- r.debugln(" unexported")
-
- funcMethod := "function"
- funcMethodName := funcDecl.Name.Name
-
- if recvName != "" {
- funcMethod = "method"
- funcMethodName = recvName + "." + funcDecl.Name.Name
- }
-
- pass.Report(analysis.Diagnostic{
- Pos: typ.Pos(),
- Message: fmt.Sprintf("unexported interface '%s' used as parameter in exported %s '%s'", typ.Name, funcMethod, funcMethodName),
- })
- }
- default:
- r.debugln(" unhandled")
- }
+ b.WriteString(typeName(idx))
}
- r.debugln(" results:")
+ b.WriteByte(']')
- results := funcDecl.Type.Results
- if results == nil {
- r.debugln(" no results")
+ return b.String()
+ default:
+ return fmt.Sprintf("%T", expr)
+ }
+}
+
+func (r *runner) checkType(pass *analysis.Pass, expr ast.Expr, funcDecl *ast.FuncDecl, recvName, role string) {
+ infoType := pass.TypesInfo.TypeOf(expr)
+
+ r.debugf(" %s: %v infoType: %v reflectType: %T\n", role, expr, infoType, expr)
+
+ ident := findIdent(expr)
+ if ident == nil {
+ r.debugln(" skip non-interface")
+
+ return
+ }
+
+ switch typ := ident.(type) {
+ case *ast.SelectorExpr:
+ r.debugln(" external")
+
+ return
+ case *ast.Ident:
+ if typ.IsExported() {
+ r.debugln(" skip exported")
return
}
+ }
- for _, result := range results.List {
- resultType := result.Type
- infoType := pass.TypesInfo.TypeOf(resultType)
+ identType := pass.TypesInfo.TypeOf(ident)
+ if identType == nil {
+ r.debugln(" skip unknown type")
- r.debugln(" resultType:", resultType, "infoType:", infoType, "reflectType:", reflect.TypeOf(resultType))
+ return
+ }
- if !types.IsInterface(infoType) {
- r.debugln(" skip non-interface")
+ errorType := types.Universe.Lookup("error").Type()
+ anyType := types.Universe.Lookup("any").Type()
- continue
- }
+ if types.Identical(identType, errorType) || types.Identical(identType, anyType) {
+ r.debugln(" skip predeclared type")
- if infoType.String() == "error" {
- // skip error interface
- r.debugln(" skip error interface")
+ return
+ }
- continue
- }
+ if !types.IsInterface(identType) {
+ r.debugln(" skip non-interface")
- if infoType.String() == "any" {
- // skip any interface
- r.debugln(" skip any interface")
+ return
+ }
- continue
- }
+ typ := ident.(*ast.Ident)
- switch typ := resultType.(type) {
- case *ast.Ident:
- if !typ.IsExported() {
- r.debugln(" unexported")
-
- funcMethod := "function"
- funcMethodName := funcDecl.Name.Name
-
- if recvName != "" {
- funcMethod = "method"
- funcMethodName = recvName + "." + funcDecl.Name.Name
- }
-
- pass.Report(analysis.Diagnostic{
- Pos: typ.Pos(),
- Message: fmt.Sprintf("unexported interface '%s' used as return value in exported %s '%s'", typ.Name, funcMethod, funcMethodName),
- })
- }
- default:
- r.debugln(" unhandled")
- }
- }
- })
+ r.debugln(" unexported")
- return nil, nil
+ funcMethod := "function"
+ funcMethodName := funcDecl.Name.Name
+
+ if recvName != "" {
+ funcMethod = "method"
+ funcMethodName = recvName + "." + funcDecl.Name.Name
+ }
+
+ pass.Report(analysis.Diagnostic{
+ Pos: typ.Pos(),
+ Message: fmt.Sprintf("unexported interface '%s' used as %s in exported %s '%s'", typeName(expr), role, funcMethod, funcMethodName),
+ })
}
func (r *runner) debugln(a ...any) {
if r.debug {
- fmt.Println(a...)
+ fmt.Fprintln(os.Stderr, a...)
+ }
+}
+
+func (r *runner) debugf(format string, a ...any) {
+ if r.debug {
+ fmt.Fprintf(os.Stderr, format, a...)
}
}
diff --git a/vendor/github.com/uudashr/iface/unused/unused.go b/vendor/github.com/uudashr/iface/unused/unused.go
index 7783eeef..743e2942 100644
--- a/vendor/github.com/uudashr/iface/unused/unused.go
+++ b/vendor/github.com/uudashr/iface/unused/unused.go
@@ -4,7 +4,7 @@ import (
"fmt"
"go/ast"
"go/token"
- "reflect"
+ "os"
"slices"
"strings"
@@ -14,7 +14,7 @@ import (
"golang.org/x/tools/go/ast/inspector"
)
-// Analyzer detects unused interfaces in the package.
+// Analyzer detects interfaces which are not used anywhere in the same package where they are defined.
var Analyzer = newAnalyzer()
func newAnalyzer() *analysis.Analyzer {
@@ -34,13 +34,27 @@ func newAnalyzer() *analysis.Analyzer {
return analyzer
}
+type ifaceEntry struct {
+ ts *ast.TypeSpec
+ decl *ast.GenDecl
+}
+
type runner struct {
debug bool
exclude string
}
func (r *runner) run(pass *analysis.Pass) (any, error) {
- excludes := strings.Split(r.exclude, ",")
+ var excludes []string
+
+ if r.exclude != "" {
+ for _, pkg := range strings.Split(r.exclude, ",") {
+ if p := strings.TrimSpace(pkg); p != "" {
+ excludes = append(excludes, p)
+ }
+ }
+ }
+
if slices.Contains(excludes, pass.Pkg.Path()) {
return nil, nil
}
@@ -48,8 +62,7 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
// Collect all interface type declarations
- ifaceDecls := make(map[string]*ast.TypeSpec)
- genDecls := make(map[string]*ast.GenDecl) // ifaceName -> GenDecl
+ ifaces := make(map[string]ifaceEntry)
nodeFilter := []ast.Node{
(*ast.GenDecl)(nil),
@@ -62,17 +75,19 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
}
if r.debug {
- fmt.Printf("GenDecl: %v specs=%d\n", decl.Tok, len(decl.Specs))
+ fmt.Fprintf(os.Stderr, "GenDecl: %v specs=%d\n", decl.Tok, len(decl.Specs))
}
if decl.Tok != token.TYPE {
return
}
+ if directive.ShouldIgnore(decl.Doc, pass.Analyzer.Name) {
+ return
+ }
+
for i, spec := range decl.Specs {
- if r.debug {
- fmt.Printf(" spec[%d]: %v %v\n", i, spec, reflect.TypeOf(spec))
- }
+ r.debugf(" spec[%d]: %v %T\n", i, spec, spec)
ts, ok := spec.(*ast.TypeSpec)
if !ok {
@@ -84,28 +99,23 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
continue
}
- if r.debug {
- fmt.Println(" Interface type declaration:", ts.Name.Name, ts.Pos())
- }
+ r.debugln(" -> Interface type declaration:", ts.Name.Name, ts.Pos())
- dir := directive.ParseIgnore(decl.Doc)
- if dir != nil && dir.ShouldIgnore(pass.Analyzer.Name) {
- // skip due to ignore directive
+ if directive.ShouldIgnore(ts.Doc, pass.Analyzer.Name) {
continue
}
- ifaceDecls[ts.Name.Name] = ts
- genDecls[ts.Name.Name] = decl
+ ifaces[ts.Name.Name] = ifaceEntry{ts: ts, decl: decl}
}
})
if r.debug {
var ifaceNames []string
- for name := range ifaceDecls {
+ for name := range ifaces {
ifaceNames = append(ifaceNames, name)
}
- fmt.Println("Declared interfaces:", ifaceNames)
+ fmt.Fprintln(os.Stderr, "Declared interfaces:", ifaceNames)
}
// Inspect whether the interface is used within the package
@@ -119,32 +129,41 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
return
}
- ts, ok := ifaceDecls[ident.Name]
+ entry, ok := ifaces[ident.Name]
if !ok {
return
}
- if ts.Pos() == ident.Pos() {
- // The identifier is the interface type declaration
+ if entry.ts.Pos() == ident.Pos() {
return
}
- delete(ifaceDecls, ident.Name)
- delete(genDecls, ident.Name)
+ delete(ifaces, ident.Name)
})
if r.debug {
- fmt.Printf("Package %s %s\n", pass.Pkg.Path(), pass.Pkg.Name())
+ fmt.Fprintf(os.Stderr, "Package %s %s\n", pass.Pkg.Path(), pass.Pkg.Name())
}
- for name, ts := range ifaceDecls {
- decl := genDecls[name]
+ for name, entry := range ifaces {
+ ts := entry.ts
+ decl := entry.decl
- var node ast.Node
+ var start, end token.Pos
if len(decl.Specs) == 1 {
- node = decl
+ start = decl.Pos()
+ if decl.Doc != nil {
+ start = decl.Doc.Pos()
+ }
+
+ end = decl.End()
} else {
- node = ts
+ start = ts.Pos()
+ if ts.Doc != nil {
+ start = ts.Doc.Pos()
+ }
+
+ end = ts.End()
}
msg := fmt.Sprintf("interface '%s' is declared but not used within the package", name)
@@ -156,8 +175,8 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
Message: "Remove the unused interface declaration",
TextEdits: []analysis.TextEdit{
{
- Pos: node.Pos(),
- End: node.End(),
+ Pos: start,
+ End: end,
NewText: []byte{},
},
},
@@ -168,3 +187,15 @@ func (r *runner) run(pass *analysis.Pass) (any, error) {
return nil, nil
}
+
+func (r *runner) debugln(a ...any) {
+ if r.debug {
+ fmt.Fprintln(os.Stderr, a...)
+ }
+}
+
+func (r *runner) debugf(format string, a ...any) {
+ if r.debug {
+ fmt.Fprintf(os.Stderr, format, a...)
+ }
+}
diff --git a/vendor/github.com/uudashr/iface/unusedmethod/doc.go b/vendor/github.com/uudashr/iface/unusedmethod/doc.go
new file mode 100644
index 00000000..cef63a7f
--- /dev/null
+++ b/vendor/github.com/uudashr/iface/unusedmethod/doc.go
@@ -0,0 +1,3 @@
+// Package unusedmethod defines an Analyzer that detects interface methods which
+// are never used anywhere in the same package where they are defined.
+package unusedmethod
diff --git a/vendor/github.com/uudashr/iface/unusedmethod/unusedmethod.go b/vendor/github.com/uudashr/iface/unusedmethod/unusedmethod.go
new file mode 100644
index 00000000..2f671465
--- /dev/null
+++ b/vendor/github.com/uudashr/iface/unusedmethod/unusedmethod.go
@@ -0,0 +1,226 @@
+package unusedmethod
+
+import (
+ "fmt"
+ "go/ast"
+ "go/token"
+ "go/types"
+ "os"
+ "slices"
+ "strings"
+
+ "github.com/uudashr/iface/internal/directive"
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+var Analyzer = newAnalyzer()
+
+func newAnalyzer() *analysis.Analyzer {
+ r := runner{}
+
+ analyzer := &analysis.Analyzer{
+ Name: "unusedmethod",
+ Doc: "Detects interface methods that are never used anywhere in the same package where they are defined.",
+ URL: "https://pkg.go.dev/github.com/uudashr/iface/unusedmethod",
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ Run: r.run,
+ }
+
+ analyzer.Flags.BoolVar(&r.debug, "nerd", false, "enable nerd mode")
+ analyzer.Flags.StringVar(&r.exclude, "exclude", "", "comma-separated list of packages to exclude from the check")
+
+ return analyzer
+}
+
+type methodEntry struct {
+ ifaceName string
+ field *ast.Field
+}
+
+type runner struct {
+ debug bool
+ exclude string
+}
+
+func (r *runner) run(pass *analysis.Pass) (any, error) {
+ var excludes []string
+
+ if r.exclude != "" {
+ for _, pkg := range strings.Split(r.exclude, ",") {
+ if p := strings.TrimSpace(pkg); p != "" {
+ excludes = append(excludes, p)
+ }
+ }
+ }
+
+ if slices.Contains(excludes, pass.Pkg.Path()) {
+ return nil, nil
+ }
+
+ inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+
+ unusedMethods := make(map[*types.Func]methodEntry)
+
+ nodeFilter := []ast.Node{
+ (*ast.GenDecl)(nil),
+ }
+
+ inspect.Preorder(nodeFilter, func(n ast.Node) {
+ decl, ok := n.(*ast.GenDecl)
+ if !ok {
+ return
+ }
+
+ if r.debug {
+ fmt.Fprintf(os.Stderr, "GenDecl: %v specs=%d\n", decl.Tok, len(decl.Specs))
+ }
+
+ if decl.Tok != token.TYPE {
+ return
+ }
+
+ if directive.ShouldIgnore(decl.Doc, pass.Analyzer.Name) {
+ return
+ }
+
+ for i, spec := range decl.Specs {
+ r.debugf(" spec[%d]: %v %T\n", i, spec, spec)
+
+ ts, ok := spec.(*ast.TypeSpec)
+ if !ok {
+ continue
+ }
+
+ ifaceType, ok := ts.Type.(*ast.InterfaceType)
+ if !ok {
+ continue
+ }
+
+ r.debugln(" -> Interface type declaration:", ts.Name.Name)
+
+ if directive.ShouldIgnore(ts.Doc, pass.Analyzer.Name) {
+ continue
+ }
+
+ for j, field := range ifaceType.Methods.List {
+ switch ft := field.Type.(type) {
+ case *ast.FuncType:
+ name := field.Names[0]
+ obj := pass.TypesInfo.Defs[name]
+
+ if r.debug {
+ fmt.Fprintf(os.Stderr, " [%d] Field: func %s %T\n", j, name.Name, ft)
+ fmt.Fprintf(os.Stderr, " obj: %v %T %p\n", obj, obj, obj)
+ }
+
+ if directive.ShouldIgnore(field.Doc, pass.Analyzer.Name) {
+ continue
+ }
+
+ if directive.ShouldIgnore(field.Comment, pass.Analyzer.Name) {
+ continue
+ }
+
+ if fn, ok := obj.(*types.Func); ok {
+ unusedMethods[fn] = methodEntry{
+ ifaceName: ts.Name.Name,
+ field: field,
+ }
+ }
+ default:
+ r.debugf(" [%d] Field: unknown %v %T\n", j, ft, ft)
+ }
+ }
+ }
+ })
+
+ // Method is always SelectorExpr
+ nodeFilter = []ast.Node{
+ (*ast.SelectorExpr)(nil),
+ }
+
+ r.debugln("Method usage")
+ inspect.Preorder(nodeFilter, func(n ast.Node) {
+ r.debugf(" n %v %T\n", n, n)
+
+ selExp, ok := n.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+
+ r.debugf(" selExp sel: %v %T, x: %v %T\n", selExp.Sel, selExp.Sel, selExp.X, selExp.X)
+
+ sel, ok := pass.TypesInfo.Selections[selExp]
+ if !ok {
+ return
+ }
+
+ if r.debug {
+ fmt.Fprintf(os.Stderr, " sel -> %v %T, kind: %v %T, obj: %v %T\n", sel, sel, sel.Kind(), sel.Kind(), sel.Obj(), sel.Obj())
+ }
+
+ fn, ok := sel.Obj().(*types.Func)
+ if !ok {
+ return
+ }
+
+ delete(unusedMethods, fn)
+ })
+
+ if r.debug {
+ fmt.Fprintf(os.Stderr, "Unused methods %d\n", len(unusedMethods))
+ }
+
+ for fn, entry := range unusedMethods {
+ if r.debug {
+ fmt.Fprintf(os.Stderr, " %v %T %s\n", fn, fn, fn.Name())
+ }
+
+ msg := fmt.Sprintf("method '%s()' is declared on interface '%s' but not used within the package", fn.Name(), entry.ifaceName)
+
+ field := entry.field
+
+ pos := field.Pos()
+ if doc := field.Doc; doc != nil {
+ pos = doc.Pos()
+ }
+
+ end := field.End()
+ if comment := field.Comment; comment != nil {
+ end = comment.End()
+ }
+
+ pass.Report(analysis.Diagnostic{
+ Pos: field.Pos(),
+ Message: msg,
+ SuggestedFixes: []analysis.SuggestedFix{
+ {
+ Message: "Remove the unused method",
+ TextEdits: []analysis.TextEdit{
+ {
+ Pos: pos,
+ End: end,
+ NewText: []byte{},
+ },
+ },
+ },
+ },
+ })
+ }
+
+ return nil, nil
+}
+
+func (r *runner) debugln(a ...any) {
+ if r.debug {
+ fmt.Fprintln(os.Stderr, a...)
+ }
+}
+
+func (r *runner) debugf(format string, a ...any) {
+ if r.debug {
+ fmt.Fprintf(os.Stderr, format, a...)
+ }
+}
diff --git a/vendor/go-simpler.org/sloglint/.golangci.yaml b/vendor/go-simpler.org/sloglint/.golangci.yaml
index cbac9150..526e368d 100644
--- a/vendor/go-simpler.org/sloglint/.golangci.yaml
+++ b/vendor/go-simpler.org/sloglint/.golangci.yaml
@@ -1,10 +1,10 @@
-# https://golangci-lint.run/usage/configuration
+# https://golangci-lint.run/docs/configuration/file
version: "2"
linters:
- default: standard
enable:
- gocritic
+ - modernize
settings:
gocritic:
enable-all: true
@@ -16,3 +16,6 @@ formatters:
enable:
- gofumpt
- goimports
+ settings:
+ gofumpt:
+ extra-rules: true
diff --git a/vendor/go-simpler.org/sloglint/.goreleaser.yaml b/vendor/go-simpler.org/sloglint/.goreleaser.yaml
new file mode 100644
index 00000000..a8fa6bbf
--- /dev/null
+++ b/vendor/go-simpler.org/sloglint/.goreleaser.yaml
@@ -0,0 +1,12 @@
+# https://goreleaser.com/customization/builds/go
+
+builds:
+ - main: ./cmd/{{.ProjectName}}
+ flags:
+ - -trimpath
+ ldflags:
+ - -s -w -X main.version={{.Version}}
+ env:
+ - CGO_ENABLED=0
+ targets:
+ - go_first_class # https://go.dev/wiki/PortingPolicy#first-class-ports
diff --git a/vendor/go-simpler.org/sloglint/.goreleaser.yml b/vendor/go-simpler.org/sloglint/.goreleaser.yml
deleted file mode 100644
index d31ea11d..00000000
--- a/vendor/go-simpler.org/sloglint/.goreleaser.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-builds:
- - main: ./cmd/sloglint
- env:
- - CGO_ENABLED=0
- flags:
- - -trimpath
- ldflags:
- - -s -w -X main.version={{.Version}}
- targets:
- - darwin_amd64
- - darwin_arm64
- - linux_amd64
- - windows_amd64
-
-archives:
- - format_overrides:
- - goos: windows
- format: zip
diff --git a/vendor/go-simpler.org/sloglint/Makefile b/vendor/go-simpler.org/sloglint/Makefile
index 6165b16f..cf5eb9d1 100644
--- a/vendor/go-simpler.org/sloglint/Makefile
+++ b/vendor/go-simpler.org/sloglint/Makefile
@@ -1,28 +1,25 @@
.POSIX:
.SUFFIXES:
-all: test lint
+help:
+ @echo 'Available commands:'
+ @echo ' build Build the project'
+ @echo ' fmt Run formatters'
+ @echo ' lint Run linters'
+ @echo ' test Run tests'
+ @echo ' test/cover Run tests and open coverage report'
-test:
- go test -race -shuffle=on -cover ./...
+build:
+ @go build -o /dev/null ./...
-test/cover:
- go test -race -shuffle=on -coverprofile=coverage.out ./...
- go tool cover -html=coverage.out
+fmt:
+ @golangci-lint fmt
lint:
- golangci-lint run
-
-tidy:
- go mod tidy
+ @golangci-lint run --fix
-generate:
- go generate ./...
-
-# run `make pre-commit` once to install the hook.
-pre-commit: .git/hooks/pre-commit test lint tidy generate
- git diff --exit-code
+test:
+ @go test -race -shuffle=on -coverprofile=coverage.out ./...
-.git/hooks/pre-commit:
- echo "make pre-commit" > .git/hooks/pre-commit
- chmod +x .git/hooks/pre-commit
+test/cover: test
+ @go tool cover -html=coverage.out
diff --git a/vendor/go-simpler.org/sloglint/README.md b/vendor/go-simpler.org/sloglint/README.md
index e75fd021..9653bd15 100644
--- a/vendor/go-simpler.org/sloglint/README.md
+++ b/vendor/go-simpler.org/sloglint/README.md
@@ -1,205 +1,296 @@
# sloglint
-[](https://github.com/go-simpler/sloglint/actions/workflows/checks.yml)
-[](https://pkg.go.dev/go-simpler.org/sloglint)
-[](https://goreportcard.com/report/go-simpler.org/sloglint)
+[](https://github.com/go-simpler/sloglint/actions/workflows/checks.yaml)
+[](https://pkg.go.dev/go-simpler.org/sloglint)
[](https://codecov.io/gh/go-simpler/sloglint)
A Go linter that ensures consistent code style when using `log/slog`.
-## 📌 About
+## Install
-The `log/slog` API allows two different types of arguments: key-value pairs and attributes.
-While people may have different opinions about which one is better, most seem to agree on one thing: it should be consistent.
-With `sloglint` you can enforce various rules for `log/slog` based on your preferred code style.
-
-## 🚀 Features
-
-* Enforce not mixing key-value pairs and attributes (default)
-* Enforce using either key-value pairs only or attributes only (optional)
-* Enforce not using global loggers (optional)
-* Enforce using methods that accept a context (optional)
-* Enforce using static messages (optional)
-* Enforce message style (optional)
-* Enforce using constants instead of raw keys (optional)
-* Enforce key naming convention (optional)
-* Enforce not using specific keys (optional)
-* Enforce putting arguments on separate lines (optional)
-
-## 📦 Install
-
-`sloglint` is integrated into [`golangci-lint`][1], and this is the recommended way to use it.
-
-To enable the linter, add the following lines to `.golangci.yml`:
+`sloglint` is part of [golangci-lint](https://golangci-lint.run), and this is the recommended way to use it.
```yaml
+# .golangci.yaml
linters:
enable:
- sloglint
```
-Alternatively, you can download a prebuilt binary from the [Releases][2] page to use `sloglint` standalone.
+Alternatively, you can download a prebuilt binary from the [Releases](https://github.com/go-simpler/sloglint/releases) page to use `sloglint` standalone.
-## 📋 Usage
+## Supported checks
-Run `golangci-lint` with `sloglint` enabled.
-See the list of [available options][3] to configure the linter.
+For `log/slog` functions:
+- [No global logger](#no-global-logger)
+- [Context only](#context-only)
+- [Discard handler](#discard-handler)
-When using `sloglint` standalone, pass the options as flags of the same name.
+For log messages:
+- [Static message](#static-message)
+- [Message style](#message-style)
-### No mixed arguments
+For log arguments:
+- [No mixed arguments](#no-mixed-arguments)
+- [Key-value pairs only](#key-value-pairs-only)
+- [Attributes only](#attributes-only)
+- [Arguments on separate lines](#arguments-on-separate-lines)
-The `no-mixed-args` option causes `sloglint` to report mixing key-values pairs and attributes within a single function call:
+For log keys:
+- [Constant keys](#constant-keys)
+- [Allowed keys](#allowed-keys)
+- [Forbidden keys](#forbidden-keys)
+- [Key naming case](#key-naming-case)
-```go
-slog.Info("a user has logged in", "user_id", 42, slog.String("ip_address", "192.0.2.0")) // sloglint: key-value pairs and attributes should not be mixed
-```
+The checks for log messages, arguments, and keys can also be used to analyze [custom functions](#custom-function-analysis).
-It is enabled by default.
-
-### Key-value pairs only
+### No global logger
-The `kv-only` option causes `sloglint` to report any use of attributes:
+Report the use of global loggers.
+Alternatively, only report the use of the `slog.Default()` logger.
```go
-slog.Info("a user has logged in", slog.Int("user_id", 42)) // sloglint: attributes should not be used
+slog.Info("a user has logged in")
+// sloglint: global logger should not be used
```
-### Attributes only
-
-In contrast, the `attr-only` option causes `sloglint` to report any use of key-value pairs:
-
-```go
-slog.Info("a user has logged in", "user_id", 42) // sloglint: key-value pairs should not be used
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ no-global: "all" # Or "default".
```
-### No global
+### Context only
-Some projects prefer to pass loggers as explicit dependencies.
-The `no-global` option causes `sloglint` to report the use of global loggers.
+Report the use of functions without a `context.Context`.
+Alternatively, only report their use if a context exists within the scope of the outermost function.
```go
-slog.Info("a user has logged in", "user_id", 42) // sloglint: global logger should not be used
+slog.Info("a user has logged in")
+// sloglint: InfoContext should be used instead
+```
+
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ context: "all" # Or "scope".
```
-Possible values are `all` (report all global loggers) and `default` (report only the default `slog` logger).
+This check partially supports autofix.
-### Context only
+### Discard handler
-Some `slog.Handler` implementations make use of the given `context.Context` (e.g. to access context values).
-For them to work properly, you need to pass a context to all logger calls.
-The `context-only` option causes `sloglint` to report the use of methods without a context:
+Suggest using `slog.DiscardHandler` when possible.
```go
-slog.Info("a user has logged in") // sloglint: InfoContext should be used instead
+slog.NewJSONHandler(io.Discard, nil)
+// sloglint: use slog.DiscardHandler instead
```
-Possible values are `all` (report all contextless calls) and `scope` (report only if a context exists in the scope of the outermost function).
+This check is enabled by default and supports autofix.
-### Static messages
+### Static message
-To get the most out of structured logging, you may want to require log messages to be static.
-The `static-msg` option causes `sloglint` to report non-static messages:
+Report dynamic log messages, such as those that are built with `fmt.Sprintf`.
```go
-slog.Info(fmt.Sprintf("a user with id %d has logged in", 42)) // sloglint: message should be a string literal or a constant
+slog.Info(fmt.Sprintf("a user with id %d has logged in", 42))
+// sloglint: message should be a string literal or a constant
+```
+
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ static-msg: true
```
-The report can be fixed by moving dynamic values to arguments:
+### Message style
+
+Report log messages that do not match a particular style.
+The supported styles are `lowercased` (the first letter is lowercase) and `capitalized` (the first letter is uppercase).
```go
-slog.Info("a user has logged in", "user_id", 42)
+slog.Info("A user has logged in")
+// sloglint: message should be lowercased
```
-### Message style
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ msg-style: "lowercased" # Or "capitalized".
+```
-The `msg-style` option causes `sloglint` to check log messages for a particular style.
+### No mixed arguments
-Possible values are `lowercased` (report messages that begin with an uppercase letter)...
+Report the use of both key-value pairs and attributes within a single function call.
```go
-slog.Info("Msg") // sloglint: message should be lowercased
+slog.Info("a user has logged in", "user_id", 42, slog.String("ip_address", "192.0.2.0"))
+// sloglint: key-value pairs and attributes should not be mixed
```
-...and `capitalized` (report messages that begin with a lowercase letter):
+This check is enabled by default.
+
+### Key-value pairs only
+
+Report any use of attributes as function call arguments.
```go
-slog.Info("msg") // sloglint: message should be capitalized
+slog.Info("a user has logged in", slog.Int("user_id", 42))
+// sloglint: attributes should not be used
```
-Special cases such as acronyms (e.g. `HTTP`, `U.S.`) are ignored.
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ kv-only: true
+```
-### No raw keys
+### Attributes only
-To prevent typos, you may want to forbid the use of raw keys altogether.
-The `no-raw-keys` option causes `sloglint` to report the use of strings as keys
-(including `slog.Attr` calls, e.g. `slog.Int("user_id", 42)`):
+Report any use of key-value pairs as function call arguments.
```go
-slog.Info("a user has logged in", "user_id", 42) // sloglint: raw keys should not be used
+slog.Info("a user has logged in", "user_id", 42)
+// sloglint: key-value pairs should not be used
+```
+
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ attr-only: true
```
-This report can be fixed by using either constants...
+### Arguments on separate lines
+
+Report two or more arguments on the same line.
+A key-value pair is considered a single argument.
```go
-const UserId = "user_id"
+slog.Info("a user has logged in", "user_id", 42, "ip_address", "192.0.2.0")
+// sloglint: arguments should be put on separate lines
+```
-slog.Info("a user has logged in", UserId, 42)
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ args-on-sep-lines: true
```
-...or custom `slog.Attr` constructors:
+### Constant keys
-```go
-func UserId(value int) slog.Attr { return slog.Int("user_id", value) }
+Report the use of string literals as log keys.
-slog.Info("a user has logged in", UserId(42))
+```go
+slog.Info("a user has logged in", "user_id", 42)
+// sloglint: the "user_id" key should be a constant
```
-> [!TIP]
-> Such helpers can be automatically generated for you by the [`sloggen`][4] tool. Give it a try too!
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ no-raw-keys: true
+```
-### Key naming convention
+### Allowed keys
-To ensure consistency in logs, you may want to enforce a single key naming convention.
-The `key-naming-case` option causes `sloglint` to report keys written in a case other than the given one:
+Report the use of log keys that are not explicitly allowed.
```go
-slog.Info("a user has logged in", "user-id", 42) // sloglint: keys should be written in snake_case
+slog.Info("a user has logged in", "id", 42)
+// sloglint: the "id" key is not allowed and should not be used
```
-Possible values are `snake`, `kebab`, `camel`, or `pascal`.
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ allowed-keys:
+ - user_id
+```
### Forbidden keys
-To prevent accidental use of reserved log keys, you may want to forbid specific keys altogether.
-The `forbidden-keys` option causes `sloglint` to report the use of forbidden keys:
+Report the use of forbidden log keys.
+When using the standard `slog.JSONHandler` or `slog.TextHandler`,
+you may want to forbid the `time`, `level`, `msg`, and `source` keys,
+as these will be written by the handler.
```go
-slog.Info("a user has logged in", "reserved", 42) // sloglint: "reserved" key is forbidden and should not be used
+slog.Info("a user has logged in", "time", time.Now())
+// sloglint: the "time" key is forbidden and should not be used
```
-For example, when using the standard `slog.JSONHandler` and `slog.TextHandler`,
-you may want to forbid the `time`, `level`, `msg`, and `source` keys, as these are used by the handlers.
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ forbidden-keys:
+ - time
+ - level
+ - msg
+ - source
+```
-### Arguments on separate lines
+### Key naming case
-To improve code readability, you may want to put arguments on separate lines, especially when using key-value pairs.
-The `args-on-sep-lines` option causes `sloglint` to report 2+ arguments on the same line:
+Report log keys that do not match a particular naming case.
+The supported cases are `snake_case`, `kebab-case`, `camelCase`, and `PascalCase`.
```go
-slog.Info("a user has logged in", "user_id", 42, "ip_address", "192.0.2.0") // sloglint: arguments should be put on separate lines
+slog.Info("a user has logged in", "user-id", 42)
+// sloglint: keys should be written in snake_case
```
-This report can be fixed by reformatting the code:
-
-```go
-slog.Info("a user has logged in",
- "user_id", 42,
- "ip_address", "192.0.2.0",
-)
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ key-naming-case: "snake" # Or "kebab", "camel", "pascal".
```
-[1]: https://golangci-lint.run
-[2]: https://github.com/go-simpler/sloglint/releases
-[3]: https://golangci-lint.run/usage/linters/#sloglint
-[4]: https://github.com/go-simpler/sloggen
+This check supports autofix.
+
+## Custom function analysis
+
+Analyze custom functions in addition to the standard `log/slog` functions.
+
+The following function properties must be specified:
+1. The full name of the function, including the package, e.g. `log/slog.Info`.
+If the function is a method, the receiver type must be wrapped in parentheses, e.g. `(*log/slog.Logger).Info`.
+2. The position of the `msg string` argument in the function signature, starting from 0.
+If there is no message in the function, a negative value must be passed.
+3. The position of the `args ...any` argument in the function signature, starting from 0.
+If there are no arguments in the function, a negative value must be passed.
+
+Here's an example for the [exp/slog](https://pkg.go.dev/golang.org/x/exp/slog) package, the predecessor of `log/slog`.
+
+```yaml
+# .golangci.yaml
+linters:
+ settings:
+ sloglint:
+ custom-funcs:
+ - name: "(*golang.org/x/exp/slog.Logger).InfoContext"
+ msg-pos: 1
+ args-pos: 2
+```
diff --git a/vendor/go-simpler.org/sloglint/analyzer.go b/vendor/go-simpler.org/sloglint/analyzer.go
new file mode 100644
index 00000000..03e43e02
--- /dev/null
+++ b/vendor/go-simpler.org/sloglint/analyzer.go
@@ -0,0 +1,209 @@
+// Package sloglint implements the sloglint analyzer.
+package sloglint
+
+import (
+ "go/ast"
+ "go/version"
+ "slices"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+ "golang.org/x/tools/go/types/typeutil"
+)
+
+// New creates a new sloglint analyzer.
+func New(opts *Options) *analysis.Analyzer {
+ if opts == nil {
+ opts = &Options{NoMixedArguments: true}
+ }
+
+ return &analysis.Analyzer{
+ Name: "sloglint",
+ Doc: "Ensures consistent code style when using log/slog.",
+ URL: "https://go-simpler.org/sloglint",
+ Flags: flags(opts),
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ Run: func(pass *analysis.Pass) (any, error) {
+ if err := opts.validate(); err != nil {
+ return nil, err
+ }
+
+ root := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Root()
+ for cursor := range root.Preorder(new(ast.CallExpr), new(ast.CompositeLit)) {
+ analyzeNode(pass, opts, cursor)
+ }
+
+ return nil, nil
+ },
+ }
+}
+
+var slogFuncs = []Func{
+ {"log/slog.Log", 2, 3},
+ {"log/slog.LogAttrs", 2, 3},
+ {"log/slog.Debug", 0, 1},
+ {"log/slog.Info", 0, 1},
+ {"log/slog.Warn", 0, 1},
+ {"log/slog.Error", 0, 1},
+ {"log/slog.DebugContext", 1, 2},
+ {"log/slog.InfoContext", 1, 2},
+ {"log/slog.WarnContext", 1, 2},
+ {"log/slog.ErrorContext", 1, 2},
+ {"log/slog.With", -1, 0},
+ {"log/slog.Group", -1, 1},
+ {"log/slog.NewTextHandler", -1, -1},
+ {"log/slog.NewJSONHandler", -1, -1},
+ {"(*log/slog.Logger).Log", 2, 3},
+ {"(*log/slog.Logger).LogAttrs", 2, 3},
+ {"(*log/slog.Logger).Debug", 0, 1},
+ {"(*log/slog.Logger).Info", 0, 1},
+ {"(*log/slog.Logger).Warn", 0, 1},
+ {"(*log/slog.Logger).Error", 0, 1},
+ {"(*log/slog.Logger).DebugContext", 1, 2},
+ {"(*log/slog.Logger).InfoContext", 1, 2},
+ {"(*log/slog.Logger).WarnContext", 1, 2},
+ {"(*log/slog.Logger).ErrorContext", 1, 2},
+ {"(*log/slog.Logger).With", -1, 0},
+}
+
+func analyzeNode(pass *analysis.Pass, opts *Options, cursor inspector.Cursor) {
+ node := cursor.Node()
+ if cl, ok := node.(*ast.CompositeLit); ok && typeName(pass.TypesInfo, cl) == "log/slog.Attr" {
+ analyzeAttrKey(pass, opts, cl)
+ return
+ }
+
+ call, ok := node.(*ast.CallExpr)
+ if !ok {
+ return
+ }
+
+ fn := typeutil.StaticCallee(pass.TypesInfo, call)
+ if fn == nil {
+ return
+ }
+
+ switch fn.FullName() {
+ case "log/slog.Int",
+ "log/slog.Int64",
+ "log/slog.Uint64",
+ "log/slog.Float64",
+ "log/slog.String",
+ "log/slog.Bool",
+ "log/slog.Time",
+ "log/slog.Duration",
+ "log/slog.Any":
+ analyzeKey(pass, opts, call.Args[0])
+ return
+ case "log/slog.Group":
+ analyzeKey(pass, opts, call.Args[0])
+ // Special case: don't return here, we also need to analyze the group's arguments.
+ }
+
+ funcs := slices.Concat(slogFuncs, opts.CustomFuncs)
+ idx := slices.IndexFunc(funcs, func(f Func) bool {
+ return f.FullName == fn.FullName()
+ })
+ if idx == -1 {
+ return
+ }
+
+ if idx < len(slogFuncs) {
+ analyzeFunction(pass, opts, call, cursor)
+ }
+ if pos := funcs[idx].MessagePos; pos >= 0 && len(call.Args) > pos {
+ analyzeMessage(pass, opts, call.Args[pos])
+ }
+ if pos := funcs[idx].ArgumentsPos; pos >= 0 && len(call.Args) > pos {
+ analyzeArguments(pass, opts, call.Args[pos:])
+ }
+}
+
+func analyzeFunction(pass *analysis.Pass, opts *Options, call *ast.CallExpr, cursor inspector.Cursor) {
+ if opts.NoGlobalLogger != "" {
+ noGlobalLogger(pass, call, opts.NoGlobalLogger == noGlobalLoggerDefault)
+ }
+ if opts.ContextOnly != "" {
+ contextOnly(pass, call, cursor, opts.ContextOnly == contextOnlyScope)
+ }
+ v := pass.Module.GoVersion // Empty in test runs.
+ if v == "" || version.Compare("go"+v, "go1.24") >= 0 {
+ discardHandler(pass, call)
+ }
+}
+
+func analyzeMessage(pass *analysis.Pass, opts *Options, msg ast.Expr) {
+ if opts.StaticMessage {
+ staticMessage(pass, msg)
+ }
+ if opts.MessageStyle != "" {
+ messageStyle(pass, msg, opts.MessageStyle)
+ }
+}
+
+func analyzeArguments(pass *analysis.Pass, opts *Options, args []ast.Expr) {
+ var keys, attrs []ast.Expr
+
+ for i := 0; i < len(args); i++ {
+ typ := pass.TypesInfo.TypeOf(args[i])
+ if typ == nil {
+ continue
+ }
+ switch typ.String() {
+ case "string":
+ keys = append(keys, args[i])
+ analyzeKey(pass, opts, args[i])
+ i++ // Skip the value.
+ case "log/slog.Attr":
+ attrs = append(attrs, args[i])
+ case "[]any", "[]log/slog.Attr":
+ continue // The last argument may be an unpacked slice, skip it.
+ }
+ }
+
+ if opts.NoMixedArguments {
+ noMixedArguments(pass, keys, attrs)
+ }
+ if opts.KeyValuePairsOnly {
+ keyValuePairsOnly(pass, attrs)
+ }
+ if opts.AttributesOnly {
+ attributesOnly(pass, keys)
+ }
+ if opts.ArgumentsOnSeparateLines {
+ argumentsOnSeparateLines(pass, keys, attrs)
+ }
+}
+
+func analyzeKey(pass *analysis.Pass, opts *Options, key ast.Expr) {
+ if opts.ConstantKeys {
+ constantKeys(pass, key)
+ }
+ if opts.KeyNamingCase != "" {
+ keyNamingCase(pass, key, opts.KeyNamingCase)
+ }
+ if len(opts.AllowedKeys) > 0 {
+ allowedKeys(pass, key, opts.AllowedKeys)
+ }
+ if len(opts.ForbiddenKeys) > 0 {
+ forbiddenKeys(pass, key, opts.ForbiddenKeys)
+ }
+}
+
+func analyzeAttrKey(pass *analysis.Pass, opts *Options, attr *ast.CompositeLit) {
+ switch len(attr.Elts) {
+ case 1:
+ if kv := attr.Elts[0].(*ast.KeyValueExpr); kv.Key.(*ast.Ident).Name == "Key" {
+ analyzeKey(pass, opts, kv.Value) // slog.Attr{Key: ...}
+ }
+ case 2:
+ if kv, ok := attr.Elts[0].(*ast.KeyValueExpr); ok && kv.Key.(*ast.Ident).Name == "Key" {
+ analyzeKey(pass, opts, kv.Value) // slog.Attr{Key: ..., Value: ...}
+ } else if kv, ok := attr.Elts[1].(*ast.KeyValueExpr); ok && kv.Key.(*ast.Ident).Name == "Key" {
+ analyzeKey(pass, opts, kv.Value) // slog.Attr{Value: ..., Key: ...}
+ } else {
+ analyzeKey(pass, opts, attr.Elts[0]) // slog.Attr{..., ...}
+ }
+ }
+}
diff --git a/vendor/go-simpler.org/sloglint/argument_checks.go b/vendor/go-simpler.org/sloglint/argument_checks.go
new file mode 100644
index 00000000..17590d7e
--- /dev/null
+++ b/vendor/go-simpler.org/sloglint/argument_checks.go
@@ -0,0 +1,55 @@
+package sloglint
+
+import (
+ "go/ast"
+ "slices"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+func noMixedArguments(pass *analysis.Pass, keys, attrs []ast.Expr) {
+ if len(keys) == 0 {
+ return
+ }
+ for _, attr := range attrs {
+ if call, ok := attr.(*ast.CallExpr); ok && funcName(pass.TypesInfo, call) == "log/slog.Group" {
+ continue // Special case: slog.Group() should always be allowed.
+ }
+ pass.ReportRangef(attr, "key-value pairs and attributes should not be mixed")
+ return
+ }
+}
+
+func keyValuePairsOnly(pass *analysis.Pass, attrs []ast.Expr) {
+ for _, attr := range attrs {
+ if call, ok := attr.(*ast.CallExpr); ok && funcName(pass.TypesInfo, call) == "log/slog.Group" {
+ continue // Special case: slog.Group() should always be allowed.
+ }
+ pass.ReportRangef(attr, "attributes should not be used")
+ return
+ }
+}
+
+func attributesOnly(pass *analysis.Pass, keys []ast.Expr) {
+ for _, key := range keys {
+ pass.ReportRangef(key, "key-value pairs should not be used")
+ return
+ }
+}
+
+func argumentsOnSeparateLines(pass *analysis.Pass, keys, attrs []ast.Expr) {
+ args := slices.Concat(keys, attrs)
+ if len(args) <= 1 {
+ return // Special case: slog.Info("msg", "key", "value") is fine.
+ }
+
+ prevLine := pass.Fset.Position(args[0].Pos()).Line
+ for _, arg := range args[1:] {
+ currLine := pass.Fset.Position(arg.Pos()).Line
+ if currLine == prevLine {
+ pass.Reportf(arg.Pos(), "arguments should be put on separate lines")
+ return
+ }
+ prevLine = currLine
+ }
+}
diff --git a/vendor/go-simpler.org/sloglint/function_checks.go b/vendor/go-simpler.org/sloglint/function_checks.go
new file mode 100644
index 00000000..7781aba6
--- /dev/null
+++ b/vendor/go-simpler.org/sloglint/function_checks.go
@@ -0,0 +1,144 @@
+package sloglint
+
+import (
+ "fmt"
+ "go/ast"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/ast/inspector"
+ "golang.org/x/tools/go/types/typeutil"
+)
+
+func noGlobalLogger(pass *analysis.Pass, call *ast.CallExpr, defaultOnly bool) {
+ fn := typeutil.StaticCallee(pass.TypesInfo, call)
+
+ switch fn.Name() {
+ case "Log", "LogAttrs",
+ "Debug", "Info", "Warn", "Error",
+ "DebugContext", "InfoContext", "WarnContext", "ErrorContext",
+ "With":
+ default:
+ return
+ }
+
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+
+ ident, ok := sel.X.(*ast.Ident)
+ if !ok {
+ return
+ }
+
+ if ident.Name == "slog" {
+ pass.ReportRangef(sel.X, "default logger should not be used")
+ return
+ }
+
+ if defaultOnly {
+ return
+ }
+
+ if obj := pass.TypesInfo.ObjectOf(ident); obj != nil && obj.Parent() == obj.Pkg().Scope() {
+ pass.ReportRangef(sel.X, "global logger should not be used")
+ }
+}
+
+func contextOnly(pass *analysis.Pass, call *ast.CallExpr, cursor inspector.Cursor, scopeOnly bool) {
+ fn := typeutil.StaticCallee(pass.TypesInfo, call)
+
+ switch fn.Name() {
+ case "Debug", "Info", "Warn", "Error":
+ default:
+ return
+ }
+
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+
+ if !scopeOnly {
+ // Don't suggest fixes here, we don't know whether there is a context in the scope.
+ pass.ReportRangef(sel.Sel, "%sContext should be used instead", fn.Name())
+ return
+ }
+
+ for cursor := range cursor.Enclosing(new(ast.FuncDecl), new(ast.FuncLit)) {
+ var params []*ast.Field
+ switch fn := cursor.Node().(type) {
+ case *ast.FuncDecl:
+ params = fn.Type.Params.List
+ case *ast.FuncLit:
+ params = fn.Type.Params.List
+ }
+
+ if len(params) == 0 {
+ continue
+ }
+
+ for _, param := range params {
+ if len(param.Names) == 0 {
+ continue
+ }
+
+ var ctxArg string
+ switch name := param.Names[0]; typeName(pass.TypesInfo, name) {
+ case "context.Context":
+ ctxArg = name.Name
+ case "*net/http.Request":
+ ctxArg = name.Name + ".Context()"
+ default:
+ continue
+ }
+
+ pass.Report(analysis.Diagnostic{
+ Pos: sel.Sel.Pos(),
+ End: sel.Sel.End(),
+ Message: fmt.Sprintf("%sContext should be used instead", fn.Name()),
+ SuggestedFixes: []analysis.SuggestedFix{{
+ TextEdits: []analysis.TextEdit{{
+ Pos: sel.Sel.Pos(),
+ End: call.Lparen + 1,
+ NewText: fmt.Appendf(nil, "%sContext(%s, ", fn.Name(), ctxArg),
+ }},
+ }},
+ })
+ return
+ }
+ }
+}
+
+func discardHandler(pass *analysis.Pass, call *ast.CallExpr) {
+ if len(call.Args) == 0 {
+ return
+ }
+
+ sel, ok := call.Args[0].(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+
+ obj := pass.TypesInfo.ObjectOf(sel.Sel)
+ if obj == nil {
+ return
+ }
+
+ if obj.Pkg().Name() != "io" || obj.Name() != "Discard" {
+ return
+ }
+
+ pass.Report(analysis.Diagnostic{
+ Pos: call.Pos(),
+ End: call.Pos(),
+ Message: "use slog.DiscardHandler instead",
+ SuggestedFixes: []analysis.SuggestedFix{{
+ TextEdits: []analysis.TextEdit{{
+ Pos: call.Pos(),
+ End: call.End(),
+ NewText: []byte("slog.DiscardHandler"),
+ }},
+ }},
+ })
+}
diff --git a/vendor/go-simpler.org/sloglint/key_checks.go b/vendor/go-simpler.org/sloglint/key_checks.go
new file mode 100644
index 00000000..c664a842
--- /dev/null
+++ b/vendor/go-simpler.org/sloglint/key_checks.go
@@ -0,0 +1,73 @@
+package sloglint
+
+import (
+ "fmt"
+ "go/ast"
+ "go/types"
+ "slices"
+ "strconv"
+
+ "github.com/ettle/strcase"
+ "golang.org/x/tools/go/analysis"
+)
+
+func constantKeys(pass *analysis.Pass, key ast.Expr) {
+ if sel, ok := key.(*ast.SelectorExpr); ok {
+ key = sel.Sel // The key is defined in another package, e.g. pkg.ConstKey.
+ }
+ if ident, ok := key.(*ast.Ident); ok {
+ if _, ok := pass.TypesInfo.ObjectOf(ident).(*types.Const); ok {
+ return
+ }
+ }
+ name, _ := keyName(key)
+ pass.ReportRangef(key, "the %q key should be a constant", name)
+}
+
+func allowedKeys(pass *analysis.Pass, key ast.Expr, allowed []string) {
+ if name, ok := keyName(key); ok && !slices.Contains(allowed, name) {
+ pass.ReportRangef(key, "the %q key is not allowed and should not be used", name)
+ }
+}
+
+func forbiddenKeys(pass *analysis.Pass, key ast.Expr, forbidden []string) {
+ if name, ok := keyName(key); ok && slices.Contains(forbidden, name) {
+ pass.ReportRangef(key, "the %q key is forbidden and should not be used", name)
+ }
+}
+
+func keyNamingCase(pass *analysis.Pass, key ast.Expr, caseName string) {
+ name, ok := keyName(key)
+ if !ok {
+ return
+ }
+
+ var caseFn func(string) string
+ switch caseName {
+ case keyNamingCaseSnake:
+ caseFn = strcase.ToSnake
+ case keyNamingCaseKebab:
+ caseFn = strcase.ToKebab
+ case keyNamingCaseCamel:
+ caseFn = strcase.ToCamel
+ case keyNamingCasePascal:
+ caseFn = strcase.ToPascal
+ }
+
+ if name == caseFn(name) {
+ return
+ }
+
+ pass.Report(analysis.Diagnostic{
+ Pos: key.Pos(),
+ End: key.End(),
+ Message: fmt.Sprintf("keys should be written in %s", caseFn(caseName+" case")),
+ SuggestedFixes: []analysis.SuggestedFix{{
+ TextEdits: []analysis.TextEdit{{
+ Pos: key.Pos(),
+ End: key.End(),
+ NewText: strconv.AppendQuote(nil, caseFn(name)),
+ }},
+ }},
+ })
+}
diff --git a/vendor/go-simpler.org/sloglint/message_checks.go b/vendor/go-simpler.org/sloglint/message_checks.go
new file mode 100644
index 00000000..746745f0
--- /dev/null
+++ b/vendor/go-simpler.org/sloglint/message_checks.go
@@ -0,0 +1,81 @@
+package sloglint
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+ "strconv"
+ "strings"
+ "unicode"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+func staticMessage(pass *analysis.Pass, msg ast.Expr) {
+ var isStatic func(msg ast.Expr) bool
+ isStatic = func(msg ast.Expr) bool {
+ switch msg := msg.(type) {
+ case *ast.BasicLit: // e.g. slog.Info("msg")
+ return msg.Kind == token.STRING
+ case *ast.Ident: // e.g. slog.Info(constMsg)
+ _, isConst := pass.TypesInfo.ObjectOf(msg).(*types.Const)
+ return isConst
+ case *ast.BinaryExpr: // e.g. slog.Info("x" + "y")
+ if msg.Op != token.ADD {
+ panic("unreachable") // Only "+" can be applied to strings.
+ }
+ return isStatic(msg.X) && isStatic(msg.Y)
+ default:
+ return false
+ }
+ }
+
+ if !isStatic(msg) {
+ pass.ReportRangef(msg, "message should be a string literal or a constant")
+ }
+}
+
+func messageStyle(pass *analysis.Pass, msg ast.Expr, style string) {
+ lit, ok := msg.(*ast.BasicLit)
+ if !ok || lit.Kind != token.STRING {
+ return
+ }
+
+ s, err := strconv.Unquote(lit.Value)
+ if err != nil {
+ panic("unreachable") // String literals are always quoted.
+ }
+
+ runes := []rune(strings.TrimSpace(s))
+ if len(runes) < 2 {
+ return
+ }
+
+ first, second := runes[0], runes[1]
+
+ if !unicode.IsLetter(first) {
+ return // e.g. "200 OK"
+ }
+
+ switch style {
+ case messageStyleLowercased:
+ if unicode.IsLower(first) {
+ return
+ }
+ if unicode.IsPunct(second) {
+ return // e.g. "U.S."
+ }
+ if unicode.IsUpper(second) {
+ return // e.g. "HTTP"
+ }
+ case messageStyleCapitalized:
+ if unicode.IsUpper(first) {
+ return
+ }
+ if unicode.IsUpper(second) {
+ return // e.g. "iPhone"
+ }
+ }
+
+ pass.ReportRangef(msg, "message should be %s", style)
+}
diff --git a/vendor/go-simpler.org/sloglint/options.go b/vendor/go-simpler.org/sloglint/options.go
new file mode 100644
index 00000000..361eb593
--- /dev/null
+++ b/vendor/go-simpler.org/sloglint/options.go
@@ -0,0 +1,152 @@
+package sloglint
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "strings"
+)
+
+// Func describes a function to analyze, e.g. [slog.Info].
+type Func struct {
+ // The full name of the function, including the package, e.g. "log/slog.Info".
+ // If the function is a method, the receiver type must be wrapped in parentheses, e.g. "(*log/slog.Logger).Info".
+ FullName string
+ // The position of the "msg string" argument in the function signature, starting from 0.
+ // If there is no message in the function, a negative value must be passed.
+ MessagePos int
+ // The position of the "args ...any" argument in the function signature, starting from 0.
+ // If there are no arguments in the function, a negative value must be passed.
+ ArgumentsPos int
+}
+
+// Options contains options for the sloglint analyzer.
+type Options struct {
+ // Report the use of global loggers ("all" or "default").
+ NoGlobalLogger string
+ // Report the use of functions without a [context.Context] ("all" or "scope").
+ ContextOnly string
+
+ // Report dynamic log messages, such as those that are built with [fmt.Sprintf].
+ StaticMessage bool
+ // Report log messages that do not match a particular style ("lowercased" or "capitalized").
+ MessageStyle string
+
+ // Report the use of both key-value pairs and attributes within a single function call (default true).
+ NoMixedArguments bool
+ // Report any use of attributes as function call arguments.
+ KeyValuePairsOnly bool
+ // Report any use of key-value pairs as function call arguments.
+ AttributesOnly bool
+ // Report two or more arguments on the same line.
+ ArgumentsOnSeparateLines bool
+
+ // Report the use of string literals as log keys.
+ ConstantKeys bool
+ // Report the use of log keys that are not explicitly allowed.
+ AllowedKeys []string
+ // Report the use of forbidden log keys.
+ ForbiddenKeys []string
+ // Report log keys that do not match a particular naming case ("snake", "kebab", "camel", or "pascal").
+ KeyNamingCase string
+
+ // Analyze custom functions in addition to the standard [log/slog] functions.
+ CustomFuncs []Func
+}
+
+// Possible values for [Options.NoGlobalLogger].
+const (
+ noGlobalLoggerAll = "all"
+ noGlobalLoggerDefault = "default"
+)
+
+// Possible values for [Options.ContextOnly].
+const (
+ contextOnlyAll = "all"
+ contextOnlyScope = "scope"
+)
+
+// Possible values for [Options.MessageStyle].
+const (
+ messageStyleLowercased = "lowercased"
+ messageStyleCapitalized = "capitalized"
+)
+
+// Possible values for [Options.KeyNamingCase].
+const (
+ keyNamingCaseSnake = "snake"
+ keyNamingCaseKebab = "kebab"
+ keyNamingCaseCamel = "camel"
+ keyNamingCasePascal = "pascal"
+)
+
+var (
+ errIncompatible = errors.New("incompatible")
+ errInvalidValue = errors.New("invalid value")
+)
+
+func (opts *Options) validate() error {
+ switch opts.NoGlobalLogger {
+ case "", noGlobalLoggerAll, noGlobalLoggerDefault:
+ default:
+ return fmt.Errorf("sloglint: Options.NoGlobalLogger has an %w %q", errInvalidValue, opts.NoGlobalLogger)
+ }
+
+ switch opts.ContextOnly {
+ case "", contextOnlyAll, contextOnlyScope:
+ default:
+ return fmt.Errorf("sloglint: Options.ContextOnly has an %w %q", errInvalidValue, opts.ContextOnly)
+ }
+
+ switch opts.MessageStyle {
+ case "", messageStyleLowercased, messageStyleCapitalized:
+ default:
+ return fmt.Errorf("sloglint: Options.MessageStyle has an %w %q", errInvalidValue, opts.MessageStyle)
+ }
+
+ if opts.KeyValuePairsOnly && opts.AttributesOnly {
+ return fmt.Errorf("sloglint: Options.KeyValuePairsOnly and Options.AttributesOnly are %w", errIncompatible)
+ }
+
+ switch opts.KeyNamingCase {
+ case "", keyNamingCaseSnake, keyNamingCaseKebab, keyNamingCaseCamel, keyNamingCasePascal:
+ default:
+ return fmt.Errorf("sloglint: Options.KeyNamingCase has an %w %q", errInvalidValue, opts.KeyNamingCase)
+ }
+
+ return nil
+}
+
+func flags(opts *Options) flag.FlagSet {
+ fs := flag.NewFlagSet("sloglint", flag.ContinueOnError)
+
+ listVar := func(p *[]string, name, usage string) {
+ fs.Func(name, usage+" (comma-separated)", func(s string) error {
+ *p = append(*p, strings.Split(s, ",")...)
+ return nil
+ })
+ }
+
+ fs.StringVar(&opts.NoGlobalLogger, "no-global", opts.NoGlobalLogger, `report the use of global loggers ("all" or "default")`)
+ fs.StringVar(&opts.ContextOnly, "ctx-only", opts.ContextOnly, `report the use of functions without a context.Context ("all" or "scope")`)
+ fs.BoolVar(&opts.StaticMessage, "static-msg", opts.StaticMessage, `report dynamic log messages, such as those that are built with fmt.Sprintf`)
+ fs.StringVar(&opts.MessageStyle, "msg-style", opts.MessageStyle, `report log messages that do not match a particular style ("lowercased" or "capitalized")`)
+ fs.BoolVar(&opts.NoMixedArguments, "no-mixed-args", opts.NoMixedArguments, `report the use of both key-value pairs and attributes within a single function call (default true)`)
+ fs.BoolVar(&opts.KeyValuePairsOnly, "kv-only", opts.KeyValuePairsOnly, `report any use of attributes as function call arguments`)
+ fs.BoolVar(&opts.AttributesOnly, "attr-only", opts.AttributesOnly, `report any use of key-value pairs as function call arguments`)
+ fs.BoolVar(&opts.ArgumentsOnSeparateLines, "args-on-sep-lines", opts.ArgumentsOnSeparateLines, `report two or more arguments on the same line`)
+ fs.BoolVar(&opts.ConstantKeys, "const-keys", opts.ConstantKeys, `report the use of string literal as log keys`)
+ listVar(&opts.AllowedKeys, "allowed-keys", `report the use of log keys that are not explicitly allowed`)
+ listVar(&opts.ForbiddenKeys, "forbidden-keys", `report the use of forbidden log keys`)
+ fs.StringVar(&opts.KeyNamingCase, "key-naming-case", opts.KeyNamingCase, `report log keys that do not match a particular naming case ("snake", "kebab", "camel", or "pascal")`)
+
+ fs.Func("fn", `analyze a custom function (format: "full-name:msg-pos:args-pos")`, func(s string) error {
+ name, rest, _ := strings.Cut(s, ":")
+ fn := Func{FullName: name}
+ _, err := fmt.Sscanf(rest, "%d:%d", &fn.MessagePos, &fn.ArgumentsPos)
+ opts.CustomFuncs = append(opts.CustomFuncs, fn)
+ return err
+ })
+
+ return *fs
+}
diff --git a/vendor/go-simpler.org/sloglint/sloglint.go b/vendor/go-simpler.org/sloglint/sloglint.go
deleted file mode 100644
index ff5d1f80..00000000
--- a/vendor/go-simpler.org/sloglint/sloglint.go
+++ /dev/null
@@ -1,576 +0,0 @@
-// Package sloglint implements the sloglint analyzer.
-package sloglint
-
-import (
- "errors"
- "flag"
- "fmt"
- "go/ast"
- "go/token"
- "go/types"
- "go/version"
- "iter"
- "slices"
- "strconv"
- "strings"
- "unicode"
-
- "github.com/ettle/strcase"
- "golang.org/x/tools/go/analysis"
- "golang.org/x/tools/go/analysis/passes/inspect"
- "golang.org/x/tools/go/ast/inspector"
- "golang.org/x/tools/go/types/typeutil"
-)
-
-// Options are options for the sloglint analyzer.
-type Options struct {
- NoMixedArgs bool // Enforce not mixing key-value pairs and attributes (default true).
- KVOnly bool // Enforce using key-value pairs only (overrides NoMixedArgs, incompatible with AttrOnly).
- AttrOnly bool // Enforce using attributes only (overrides NoMixedArgs, incompatible with KVOnly).
- NoGlobal string // Enforce not using global loggers ("all" or "default").
- ContextOnly string // Enforce using methods that accept a context ("all" or "scope").
- StaticMsg bool // Enforce using static messages.
- MsgStyle string // Enforce message style ("lowercased" or "capitalized").
- NoRawKeys bool // Enforce using constants instead of raw keys.
- KeyNamingCase string // Enforce key naming convention ("snake", "kebab", "camel", or "pascal").
- ForbiddenKeys []string // Enforce not using specific keys.
- ArgsOnSepLines bool // Enforce putting arguments on separate lines.
-
- go124 bool
-}
-
-// New creates a new sloglint analyzer.
-func New(opts *Options) *analysis.Analyzer {
- if opts == nil {
- opts = &Options{NoMixedArgs: true}
- }
-
- return &analysis.Analyzer{
- Name: "sloglint",
- Doc: "ensure consistent code style when using log/slog",
- Flags: flags(opts),
- Requires: []*analysis.Analyzer{inspect.Analyzer},
- Run: func(pass *analysis.Pass) (any, error) {
- if opts.KVOnly && opts.AttrOnly {
- return nil, fmt.Errorf("sloglint: Options.KVOnly and Options.AttrOnly: %w", errIncompatible)
- }
-
- switch opts.NoGlobal {
- case "", "all", "default":
- default:
- return nil, fmt.Errorf("sloglint: Options.NoGlobal=%s: %w", opts.NoGlobal, errInvalidValue)
- }
-
- switch opts.ContextOnly {
- case "", "all", "scope":
- default:
- return nil, fmt.Errorf("sloglint: Options.ContextOnly=%s: %w", opts.ContextOnly, errInvalidValue)
- }
-
- switch opts.MsgStyle {
- case "", styleLowercased, styleCapitalized:
- default:
- return nil, fmt.Errorf("sloglint: Options.MsgStyle=%s: %w", opts.MsgStyle, errInvalidValue)
- }
-
- switch opts.KeyNamingCase {
- case "", snakeCase, kebabCase, camelCase, pascalCase:
- default:
- return nil, fmt.Errorf("sloglint: Options.KeyNamingCase=%s: %w", opts.KeyNamingCase, errInvalidValue)
- }
-
- if version.Compare("go"+pass.Module.GoVersion, "go1.24") >= 0 {
- opts.go124 = true
- }
-
- run(pass, opts)
- return nil, nil
- },
- }
-}
-
-var (
- errIncompatible = errors.New("incompatible options")
- errInvalidValue = errors.New("invalid value")
-)
-
-func flags(opts *Options) flag.FlagSet {
- fset := flag.NewFlagSet("sloglint", flag.ContinueOnError)
-
- boolVar := func(value *bool, name, usage string) {
- fset.Func(name, usage, func(s string) error {
- v, err := strconv.ParseBool(s)
- *value = v
- return err
- })
- }
-
- strVar := func(value *string, name, usage string) {
- fset.Func(name, usage, func(s string) error {
- *value = s
- return nil
- })
- }
-
- boolVar(&opts.NoMixedArgs, "no-mixed-args", "enforce not mixing key-value pairs and attributes (default true)")
- boolVar(&opts.KVOnly, "kv-only", "enforce using key-value pairs only (overrides -no-mixed-args, incompatible with -attr-only)")
- boolVar(&opts.AttrOnly, "attr-only", "enforce using attributes only (overrides -no-mixed-args, incompatible with -kv-only)")
- strVar(&opts.NoGlobal, "no-global", "enforce not using global loggers (all|default)")
- strVar(&opts.ContextOnly, "context-only", "enforce using methods that accept a context (all|scope)")
- boolVar(&opts.StaticMsg, "static-msg", "enforce using static messages")
- strVar(&opts.MsgStyle, "msg-style", "enforce message style (lowercased|capitalized)")
- boolVar(&opts.NoRawKeys, "no-raw-keys", "enforce using constants instead of raw keys")
- strVar(&opts.KeyNamingCase, "key-naming-case", "enforce key naming convention (snake|kebab|camel|pascal)")
- boolVar(&opts.ArgsOnSepLines, "args-on-sep-lines", "enforce putting arguments on separate lines")
-
- fset.Func("forbidden-keys", "enforce not using specific keys (comma-separated)", func(s string) error {
- opts.ForbiddenKeys = append(opts.ForbiddenKeys, strings.Split(s, ",")...)
- return nil
- })
-
- return *fset
-}
-
-var slogFuncs = map[string]struct {
- argsPos int
- skipContextCheck bool
-}{
- "log/slog.With": {argsPos: 0, skipContextCheck: true},
- "log/slog.Log": {argsPos: 3},
- "log/slog.LogAttrs": {argsPos: 3},
- "log/slog.Debug": {argsPos: 1},
- "log/slog.Info": {argsPos: 1},
- "log/slog.Warn": {argsPos: 1},
- "log/slog.Error": {argsPos: 1},
- "log/slog.DebugContext": {argsPos: 2},
- "log/slog.InfoContext": {argsPos: 2},
- "log/slog.WarnContext": {argsPos: 2},
- "log/slog.ErrorContext": {argsPos: 2},
- "(*log/slog.Logger).With": {argsPos: 0, skipContextCheck: true},
- "(*log/slog.Logger).Log": {argsPos: 3},
- "(*log/slog.Logger).LogAttrs": {argsPos: 3},
- "(*log/slog.Logger).Debug": {argsPos: 1},
- "(*log/slog.Logger).Info": {argsPos: 1},
- "(*log/slog.Logger).Warn": {argsPos: 1},
- "(*log/slog.Logger).Error": {argsPos: 1},
- "(*log/slog.Logger).DebugContext": {argsPos: 2},
- "(*log/slog.Logger).InfoContext": {argsPos: 2},
- "(*log/slog.Logger).WarnContext": {argsPos: 2},
- "(*log/slog.Logger).ErrorContext": {argsPos: 2},
-}
-
-var attrFuncs = map[string]struct{}{
- "log/slog.String": {},
- "log/slog.Int64": {},
- "log/slog.Int": {},
- "log/slog.Uint64": {},
- "log/slog.Float64": {},
- "log/slog.Bool": {},
- "log/slog.Time": {},
- "log/slog.Duration": {},
- "log/slog.Group": {},
- "log/slog.Any": {},
-}
-
-// message styles.
-const (
- styleLowercased = "lowercased"
- styleCapitalized = "capitalized"
-)
-
-// key naming conventions.
-const (
- snakeCase = "snake"
- kebabCase = "kebab"
- camelCase = "camel"
- pascalCase = "pascal"
-)
-
-func run(pass *analysis.Pass, opts *Options) {
- visitor := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
- filter := []ast.Node{(*ast.CallExpr)(nil)}
-
- // WithStack is ~2x slower than Preorder, use it only when stack is needed.
- if opts.ContextOnly == "scope" {
- visitor.WithStack(filter, func(node ast.Node, _ bool, stack []ast.Node) bool {
- visit(pass, opts, node, stack)
- return false
- })
- return
- }
-
- visitor.Preorder(filter, func(node ast.Node) {
- visit(pass, opts, node, nil)
- })
-}
-
-// NOTE: stack is nil if Preorder is used.
-func visit(pass *analysis.Pass, opts *Options, node ast.Node, stack []ast.Node) {
- call := node.(*ast.CallExpr)
-
- fn := typeutil.StaticCallee(pass.TypesInfo, call)
- if fn == nil {
- return
- }
-
- name := fn.FullName()
-
- checkDiscardHandler(opts, pass, name, call)
-
- funcInfo, ok := slogFuncs[name]
- if !ok {
- return
- }
-
- switch opts.NoGlobal {
- case "all":
- if strings.HasPrefix(name, "log/slog.") || isGlobalLoggerUsed(pass.TypesInfo, call.Fun) {
- pass.Reportf(call.Pos(), "global logger should not be used")
- }
- case "default":
- if strings.HasPrefix(name, "log/slog.") {
- pass.Reportf(call.Pos(), "default logger should not be used")
- }
- }
-
- // NOTE: "With" functions are not checked for context.Context.
- if !funcInfo.skipContextCheck {
- switch opts.ContextOnly {
- case "all":
- typ := pass.TypesInfo.TypeOf(call.Args[0])
- if typ != nil && typ.String() != "context.Context" {
- pass.Reportf(call.Pos(), "%sContext should be used instead", fn.Name())
- }
- case "scope":
- typ := pass.TypesInfo.TypeOf(call.Args[0])
- if typ != nil && typ.String() != "context.Context" && isContextInScope(pass.TypesInfo, stack) {
- pass.Reportf(call.Pos(), "%sContext should be used instead", fn.Name())
- }
- }
- }
-
- msgPos := funcInfo.argsPos - 1
-
- // NOTE: "With" functions have no message argument and must be skipped.
- if opts.StaticMsg && msgPos >= 0 && !isStaticMsg(pass.TypesInfo, call.Args[msgPos]) {
- pass.Reportf(call.Args[msgPos].Pos(), "message should be a string literal or a constant")
- }
-
- if opts.MsgStyle != "" && msgPos >= 0 {
- if lit, ok := call.Args[msgPos].(*ast.BasicLit); ok && lit.Kind == token.STRING {
- value, err := strconv.Unquote(lit.Value)
- if err != nil {
- panic("unreachable") // string literals are always quoted.
- }
- if ok := isValidMsgStyle(value, opts.MsgStyle); !ok {
- pass.Reportf(call.Args[msgPos].Pos(), "message should be %s", opts.MsgStyle)
- }
- }
- }
-
- // NOTE: we assume that the arguments have already been validated by govet.
- args := call.Args[funcInfo.argsPos:]
- if len(args) == 0 {
- return
- }
-
- var keys []ast.Expr
- var attrs []ast.Expr
-
- for i := 0; i < len(args); i++ {
- typ := pass.TypesInfo.TypeOf(args[i])
- if typ == nil {
- continue
- }
- switch typ.String() {
- case "string":
- keys = append(keys, args[i])
- i++ // skip the value.
- case "log/slog.Attr":
- attrs = append(attrs, args[i])
- case "[]any", "[]log/slog.Attr":
- continue // the last argument may be an unpacked slice, skip it.
- }
- }
-
- switch {
- case opts.KVOnly && len(attrs) > 0:
- pass.Reportf(call.Pos(), "attributes should not be used")
- case opts.AttrOnly && len(keys) > 0:
- pass.Reportf(call.Pos(), "key-value pairs should not be used")
- case opts.NoMixedArgs && len(attrs) > 0 && len(keys) > 0:
- pass.Reportf(call.Pos(), "key-value pairs and attributes should not be mixed")
- }
-
- if opts.NoRawKeys {
- for key := range AllKeys(pass.TypesInfo, keys, attrs) {
- if sel, ok := key.(*ast.SelectorExpr); ok {
- key = sel.Sel // the key is defined in another package, e.g. pkg.ConstKey.
- }
-
- isConst := false
-
- if ident, ok := key.(*ast.Ident); ok {
- if obj := pass.TypesInfo.ObjectOf(ident); obj != nil {
- if _, ok := obj.(*types.Const); ok {
- isConst = true
- }
- }
- }
-
- if !isConst {
- pass.Reportf(key.Pos(), "raw keys should not be used")
- }
- }
- }
-
- checkKeysNaming(opts, pass, keys, attrs)
-
- if len(opts.ForbiddenKeys) > 0 {
- for key := range AllKeys(pass.TypesInfo, keys, attrs) {
- if name, ok := getKeyName(key); ok && slices.Contains(opts.ForbiddenKeys, name) {
- pass.Reportf(key.Pos(), "%q key is forbidden and should not be used", name)
- }
- }
- }
-
- if opts.ArgsOnSepLines && areArgsOnSameLine(pass.Fset, call, keys, attrs) {
- pass.Reportf(call.Pos(), "arguments should be put on separate lines")
- }
-}
-
-func checkKeysNaming(opts *Options, pass *analysis.Pass, keys, attrs []ast.Expr) {
- checkKeyNamingCase := func(caseFn func(string) string, caseName string) {
- for key := range AllKeys(pass.TypesInfo, keys, attrs) {
- name, ok := getKeyName(key)
- if !ok || name == caseFn(name) {
- return
- }
-
- pass.Report(analysis.Diagnostic{
- Pos: key.Pos(),
- Message: fmt.Sprintf("keys should be written in %s", caseName),
- SuggestedFixes: []analysis.SuggestedFix{{
- TextEdits: []analysis.TextEdit{{
- Pos: key.Pos(),
- End: key.End(),
- NewText: []byte(strconv.Quote(caseFn(name))),
- }},
- }},
- })
- }
- }
-
- switch opts.KeyNamingCase {
- case snakeCase:
- checkKeyNamingCase(strcase.ToSnake, "snake_case")
- case kebabCase:
- checkKeyNamingCase(strcase.ToKebab, "kebab-case")
- case camelCase:
- checkKeyNamingCase(strcase.ToCamel, "camelCase")
- case pascalCase:
- checkKeyNamingCase(strcase.ToPascal, "PascalCase")
- }
-}
-
-func checkDiscardHandler(opts *Options, pass *analysis.Pass, name string, call *ast.CallExpr) {
- if !opts.go124 {
- return
- }
-
- if name != "log/slog.NewTextHandler" && name != "log/slog.NewJSONHandler" {
- return
- }
-
- sel, ok := call.Args[0].(*ast.SelectorExpr)
- if !ok {
- return
- }
-
- obj := pass.TypesInfo.ObjectOf(sel.Sel)
- if obj == nil {
- return
- }
-
- if obj.Pkg().Name() != "io" || obj.Name() != "Discard" {
- return
- }
-
- pass.Report(analysis.Diagnostic{
- Pos: call.Pos(),
- Message: "use slog.DiscardHandler instead",
- SuggestedFixes: []analysis.SuggestedFix{{
- TextEdits: []analysis.TextEdit{{
- Pos: call.Pos(),
- End: call.End(),
- NewText: []byte("slog.DiscardHandler"),
- }},
- }},
- })
-}
-
-func isGlobalLoggerUsed(info *types.Info, call ast.Expr) bool {
- sel, ok := call.(*ast.SelectorExpr)
- if !ok {
- return false
- }
- ident, ok := sel.X.(*ast.Ident)
- if !ok {
- return false
- }
- obj := info.ObjectOf(ident)
- return obj.Parent() == obj.Pkg().Scope()
-}
-
-func isContextInScope(info *types.Info, stack []ast.Node) bool {
- for i := len(stack) - 1; i >= 0; i-- {
- decl, ok := stack[i].(*ast.FuncDecl)
- if !ok {
- continue
- }
- params := decl.Type.Params
- if len(params.List) == 0 || len(params.List[0].Names) == 0 {
- continue
- }
- typ := info.TypeOf(params.List[0].Names[0])
- if typ != nil && typ.String() == "context.Context" {
- return true
- }
- }
- return false
-}
-
-func isStaticMsg(info *types.Info, msg ast.Expr) bool {
- switch msg := msg.(type) {
- case *ast.BasicLit: // e.g. slog.Info("msg")
- return msg.Kind == token.STRING
- case *ast.Ident: // e.g. const msg = "msg"; slog.Info(msg)
- _, isConst := info.ObjectOf(msg).(*types.Const)
- return isConst
- case *ast.BinaryExpr: // e.g. slog.Info("x" + "y")
- if msg.Op != token.ADD {
- panic("unreachable") // only + can be applied to strings.
- }
- return isStaticMsg(info, msg.X) && isStaticMsg(info, msg.Y)
- default:
- return false
- }
-}
-
-func isValidMsgStyle(msg, style string) bool {
- runes := []rune(msg)
- if len(runes) < 2 {
- return true
- }
-
- first, second := runes[0], runes[1]
-
- switch style {
- case styleLowercased:
- if unicode.IsLower(first) {
- return true
- }
- if unicode.IsPunct(second) {
- return true // e.g. "U.S.A."
- }
- return unicode.IsUpper(second) // e.g. "HTTP"
- case styleCapitalized:
- if unicode.IsUpper(first) {
- return true
- }
- return unicode.IsUpper(second) // e.g. "iPhone"
- default:
- panic("unreachable")
- }
-}
-
-func AllKeys(info *types.Info, keys, attrs []ast.Expr) iter.Seq[ast.Expr] {
- return func(yield func(key ast.Expr) bool) {
- for _, key := range keys {
- if !yield(key) {
- return
- }
- }
-
- for _, attr := range attrs {
- switch attr := attr.(type) {
- case *ast.CallExpr: // e.g. slog.Int()
- callee := typeutil.StaticCallee(info, attr)
- if callee == nil {
- continue
- }
- if _, ok := attrFuncs[callee.FullName()]; !ok {
- continue
- }
-
- if !yield(attr.Args[0]) {
- return
- }
-
- case *ast.CompositeLit: // slog.Attr{}
- switch len(attr.Elts) {
- case 1: // slog.Attr{Key: ...} | slog.Attr{Value: ...}
- if kv := attr.Elts[0].(*ast.KeyValueExpr); kv.Key.(*ast.Ident).Name == "Key" {
- if !yield(kv.Value) {
- return
- }
- }
-
- case 2: // slog.Attr{Key: ..., Value: ...} | slog.Attr{Value: ..., Key: ...} | slog.Attr{..., ...}
- if kv, ok := attr.Elts[0].(*ast.KeyValueExpr); ok && kv.Key.(*ast.Ident).Name == "Key" {
- if !yield(kv.Value) {
- return
- }
- } else if kv, ok := attr.Elts[1].(*ast.KeyValueExpr); ok && kv.Key.(*ast.Ident).Name == "Key" {
- if !yield(kv.Value) {
- return
- }
- } else {
- if !yield(attr.Elts[0]) {
- return
- }
- }
- }
- }
- }
- }
-}
-
-func getKeyName(key ast.Expr) (string, bool) {
- if ident, ok := key.(*ast.Ident); ok {
- if ident.Obj == nil || ident.Obj.Decl == nil || ident.Obj.Kind != ast.Con {
- return "", false
- }
- if spec, ok := ident.Obj.Decl.(*ast.ValueSpec); ok && len(spec.Values) > 0 {
- // TODO: support len(spec.Values) > 1; e.g. const foo, bar = 1, 2
- key = spec.Values[0]
- }
- }
- if lit, ok := key.(*ast.BasicLit); ok && lit.Kind == token.STRING {
- value, err := strconv.Unquote(lit.Value)
- if err != nil {
- panic("unreachable") // string literals are always quoted.
- }
- return value, true
- }
- return "", false
-}
-
-func areArgsOnSameLine(fset *token.FileSet, call ast.Expr, keys, attrs []ast.Expr) bool {
- if len(keys)+len(attrs) <= 1 {
- return false // special case: slog.Info("msg", "key", "value") is ok.
- }
-
- args := slices.Concat([]ast.Expr{call}, keys, attrs)
-
- lines := make(map[int]struct{}, len(args))
- for _, arg := range args {
- line := fset.Position(arg.Pos()).Line
- if _, ok := lines[line]; ok {
- return true
- }
- lines[line] = struct{}{}
- }
-
- return false
-}
diff --git a/vendor/go-simpler.org/sloglint/utils.go b/vendor/go-simpler.org/sloglint/utils.go
new file mode 100644
index 00000000..7e86e772
--- /dev/null
+++ b/vendor/go-simpler.org/sloglint/utils.go
@@ -0,0 +1,47 @@
+package sloglint
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+ "strconv"
+
+ "golang.org/x/tools/go/types/typeutil"
+)
+
+func typeName(info *types.Info, expr ast.Expr) string {
+ if typ := info.TypeOf(expr); typ != nil {
+ return typ.String()
+ }
+ return ""
+}
+
+func funcName(info *types.Info, call *ast.CallExpr) string {
+ if fn := typeutil.StaticCallee(info, call); fn != nil {
+ return fn.FullName()
+ }
+ return ""
+}
+
+func keyName(key ast.Expr) (string, bool) {
+ if ident, ok := key.(*ast.Ident); ok {
+ if ident.Obj == nil || ident.Obj.Decl == nil || ident.Obj.Kind != ast.Con {
+ return "", false
+ }
+ if spec, ok := ident.Obj.Decl.(*ast.ValueSpec); ok && len(spec.Values) > 0 {
+ key = spec.Values[0] // TODO: Support len(spec.Values) > 1; e.g. const foo, bar = 1, 2.
+ }
+ }
+
+ lit, ok := key.(*ast.BasicLit)
+ if !ok || lit.Kind != token.STRING {
+ return "", false
+ }
+
+ name, err := strconv.Unquote(lit.Value)
+ if err != nil {
+ panic("unreachable") // String literals are always quoted.
+ }
+
+ return name, true
+}
diff --git a/vendor/go.augendre.info/fatcontext/pkg/analyzer/analyzer.go b/vendor/go.augendre.info/fatcontext/pkg/analyzer/analyzer.go
index 88c75bdb..82972e42 100644
--- a/vendor/go.augendre.info/fatcontext/pkg/analyzer/analyzer.go
+++ b/vendor/go.augendre.info/fatcontext/pkg/analyzer/analyzer.go
@@ -15,9 +15,13 @@ import (
"golang.org/x/tools/go/ast/inspector"
)
-// FlagCheckStructPointers is a possible flag for the analyzer.
-// Exported to make it usable in golangci-lint.
-const FlagCheckStructPointers = "check-struct-pointers"
+// Flags for the analyzer.
+// Exported to make them usable in golangci-lint.
+const (
+ FlagCheckStructPointers = "check-struct-pointers"
+ FlagCheckLoops = "check-loops"
+ FlagCheckFunctionLiterals = "check-function-literals"
+)
// NewAnalyzer returns a fatcontext analyzer.
func NewAnalyzer() *analysis.Analyzer {
@@ -26,6 +30,10 @@ func NewAnalyzer() *analysis.Analyzer {
flags := flag.NewFlagSet("fatcontext", flag.ExitOnError)
flags.BoolVar(&rnnr.DetectInStructPointers, FlagCheckStructPointers, false,
"set to true to detect potential fat contexts in struct pointers")
+ flags.BoolVar(&rnnr.CheckLoops, FlagCheckLoops, true,
+ "set to false to disable detection of fat contexts in loops")
+ flags.BoolVar(&rnnr.CheckFunctionLiterals, FlagCheckFunctionLiterals, true,
+ "set to false to disable detection of fat contexts in function literals")
return &analysis.Analyzer{
Name: "fatcontext",
@@ -50,9 +58,11 @@ const (
type runner struct {
DetectInStructPointers bool
+ CheckLoops bool
+ CheckFunctionLiterals bool
}
-func (r *runner) run(pass *analysis.Pass) (interface{}, error) {
+func (r *runner) run(pass *analysis.Pass) (any, error) {
inspctr, typeValid := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
if !typeValid {
return nil, errInvalidAnalysis
@@ -99,7 +109,16 @@ func (r *runner) run(pass *analysis.Pass) (interface{}, error) {
}
func (r *runner) shouldIgnoreReport(category string) bool {
- return category == categoryInStructPointer && !r.DetectInStructPointers
+ switch category {
+ case categoryInLoop:
+ return !r.CheckLoops
+ case categoryInFuncLit:
+ return !r.CheckFunctionLiterals
+ case categoryInStructPointer:
+ return !r.DetectInStructPointers
+ }
+
+ return false
}
func (r *runner) getSuggestedFixes(
@@ -268,7 +287,7 @@ func getStmtList(stmt ast.Stmt) []ast.Stmt {
}
// render returns the pretty-print of the given node.
-func render(fset *token.FileSet, x interface{}) ([]byte, error) {
+func render(fset *token.FileSet, x any) ([]byte, error) {
var buf bytes.Buffer
err := printer.Fprint(&buf, fset, x)
diff --git a/vendor/go.yaml.in/yaml/v3/parserc.go b/vendor/go.yaml.in/yaml/v3/parserc.go
index 25fe8236..f35829db 100644
--- a/vendor/go.yaml.in/yaml/v3/parserc.go
+++ b/vendor/go.yaml.in/yaml/v3/parserc.go
@@ -226,9 +226,9 @@ func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool
}
// Parse the production:
-// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
//
-// ************
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// ************
func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -249,13 +249,11 @@ func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t)
}
// Parse the productions:
-// implicit_document ::= block_node DOCUMENT-END*
-//
-// *
//
-// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
-//
-// *************************
+// implicit_document ::= block_node DOCUMENT-END*
+// *
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// *************************
func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
token := peek_token(parser)
@@ -359,9 +357,9 @@ func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t
}
// Parse the productions:
-// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
//
-// ***********
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// ***********
func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -382,11 +380,10 @@ func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event
}
// Parse the productions:
-// implicit_document ::= block_node DOCUMENT-END*
-//
-// *************
//
-// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// implicit_document ::= block_node DOCUMENT-END*
+// *************
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -432,42 +429,32 @@ func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t)
}
// Parse the productions:
-// block_node_or_indentless_sequence ::=
-//
-// ALIAS
-// *****
-// | properties (block_content | indentless_block_sequence)?
-// ********** *
-// | block_content | indentless_block_sequence
-// *
-//
-// block_node ::= ALIAS
-//
-// *****
-// | properties block_content?
-// ********** *
-// | block_content
-// *
-//
-// flow_node ::= ALIAS
-//
-// *****
-// | properties flow_content?
-// ********** *
-// | flow_content
-// *
-//
-// properties ::= TAG ANCHOR? | ANCHOR TAG?
-//
-// *************************
-//
-// block_content ::= block_collection | flow_collection | SCALAR
-//
-// ******
//
-// flow_content ::= flow_collection | SCALAR
-//
-// ******
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// *****
+// | properties (block_content | indentless_block_sequence)?
+// ********** *
+// | block_content | indentless_block_sequence
+// *
+// block_node ::= ALIAS
+// *****
+// | properties block_content?
+// ********** *
+// | block_content
+// *
+// flow_node ::= ALIAS
+// *****
+// | properties flow_content?
+// ********** *
+// | flow_content
+// *
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// *************************
+// block_content ::= block_collection | flow_collection | SCALAR
+// ******
+// flow_content ::= flow_collection | SCALAR
+// ******
func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
@@ -697,9 +684,9 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
}
// Parse the productions:
-// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
//
-// ******************** *********** * *********
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// ******************** *********** * *********
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -755,9 +742,9 @@ func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_e
}
// Parse the productions:
-// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
//
-// *********** *
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// *********** *
func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -821,15 +808,15 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
}
// Parse the productions:
-// block_mapping ::= BLOCK-MAPPING_START
//
-// *******************
-// ((KEY block_node_or_indentless_sequence?)?
-// *** *
-// (VALUE block_node_or_indentless_sequence?)?)*
+// block_mapping ::= BLOCK-MAPPING_START
+// *******************
+// ((KEY block_node_or_indentless_sequence?)?
+// *** *
+// (VALUE block_node_or_indentless_sequence?)?)*
//
-// BLOCK-END
-// *********
+// BLOCK-END
+// *********
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -896,13 +883,14 @@ func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_even
}
// Parse the productions:
-// block_mapping ::= BLOCK-MAPPING_START
//
-// ((KEY block_node_or_indentless_sequence?)?
+// block_mapping ::= BLOCK-MAPPING_START
+//
+// ((KEY block_node_or_indentless_sequence?)?
//
-// (VALUE block_node_or_indentless_sequence?)?)*
-// ***** *
-// BLOCK-END
+// (VALUE block_node_or_indentless_sequence?)?)*
+// ***** *
+// BLOCK-END
func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -929,19 +917,17 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
}
// Parse the productions:
-// flow_sequence ::= FLOW-SEQUENCE-START
-//
-// *******************
-// (flow_sequence_entry FLOW-ENTRY)*
-// * **********
-// flow_sequence_entry?
-// *
-// FLOW-SEQUENCE-END
-// *****************
//
-// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
-//
-// *
+// flow_sequence ::= FLOW-SEQUENCE-START
+// *******************
+// (flow_sequence_entry FLOW-ENTRY)*
+// * **********
+// flow_sequence_entry?
+// *
+// FLOW-SEQUENCE-END
+// *****************
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -1005,9 +991,9 @@ func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_ev
}
// Parse the productions:
-// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
//
-// *** *
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *** *
func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -1026,9 +1012,9 @@ func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, ev
}
// Parse the productions:
-// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
//
-// ***** *
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// ***** *
func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -1050,9 +1036,9 @@ func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t,
}
// Parse the productions:
-// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
//
-// *
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -1068,18 +1054,17 @@ func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, ev
}
// Parse the productions:
-// flow_mapping ::= FLOW-MAPPING-START
-//
-// ******************
-// (flow_mapping_entry FLOW-ENTRY)*
-// * **********
-// flow_mapping_entry?
-// ******************
-// FLOW-MAPPING-END
-// ****************
//
-// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
-// - *** *
+// flow_mapping ::= FLOW-MAPPING-START
+// ******************
+// (flow_mapping_entry FLOW-ENTRY)*
+// * **********
+// flow_mapping_entry?
+// ******************
+// FLOW-MAPPING-END
+// ****************
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * *** *
func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -1144,8 +1129,9 @@ func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event
}
// Parse the productions:
-// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
-// - ***** *
+//
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * ***** *
func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
token := peek_token(parser)
if token == nil {
diff --git a/vendor/go.yaml.in/yaml/v3/yamlh.go b/vendor/go.yaml.in/yaml/v3/yamlh.go
index f59aa40f..07c44236 100644
--- a/vendor/go.yaml.in/yaml/v3/yamlh.go
+++ b/vendor/go.yaml.in/yaml/v3/yamlh.go
@@ -433,21 +433,19 @@ type yaml_document_t struct {
// The prototype of a read handler.
//
-// The read handler is called when the parser needs to read more bytes from the
-// source. The handler should write not more than size bytes to the buffer.
-// The number of written bytes should be set to the size_read variable.
+// The read handler is called when the parser needs to read more bytes from the
+// source. The handler should write not more than size bytes to the buffer.
+// The number of written bytes should be set to the size_read variable.
//
-// [in,out] data A pointer to an application data specified by
+// [in,out] data A pointer to an application data specified by
+// yaml_parser_set_input().
+// [out] buffer The buffer to write the data from the source.
+// [in] size The size of the buffer.
+// [out] size_read The actual number of bytes read from the source.
//
-// yaml_parser_set_input().
-//
-// [out] buffer The buffer to write the data from the source.
-// [in] size The size of the buffer.
-// [out] size_read The actual number of bytes read from the source.
-//
-// On success, the handler should return 1. If the handler failed,
-// the returned value should be 0. On EOF, the handler should set the
-// size_read to 0 and return 1.
+// On success, the handler should return 1. If the handler failed,
+// the returned value should be 0. On EOF, the handler should set the
+// size_read to 0 and return 1.
type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
// This structure holds information about a potential simple key.
@@ -655,19 +653,17 @@ type yaml_comment_t struct {
// The prototype of a write handler.
//
-// The write handler is called when the emitter needs to flush the accumulated
-// characters to the output. The handler should write @a size bytes of the
-// @a buffer to the output.
-//
-// @param[in,out] data A pointer to an application data specified by
-//
-// yaml_emitter_set_output().
+// The write handler is called when the emitter needs to flush the accumulated
+// characters to the output. The handler should write @a size bytes of the
+// @a buffer to the output.
//
-// @param[in] buffer The buffer with bytes to be written.
-// @param[in] size The size of the buffer.
+// @param[in,out] data A pointer to an application data specified by
+// yaml_emitter_set_output().
+// @param[in] buffer The buffer with bytes to be written.
+// @param[in] size The size of the buffer.
//
-// @returns On success, the handler should return @c 1. If the handler failed,
-// the returned value should be @c 0.
+// @returns On success, the handler should return @c 1. If the handler failed,
+// the returned value should be @c 0.
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
type yaml_emitter_state_t int
diff --git a/vendor/golang.org/x/exp/typeparams/common.go b/vendor/golang.org/x/exp/typeparams/common.go
index 820ca7bd..c2dd4a19 100644
--- a/vendor/golang.org/x/exp/typeparams/common.go
+++ b/vendor/golang.org/x/exp/typeparams/common.go
@@ -8,10 +8,7 @@
// Many of the types and functions in this package are proxies for the new APIs
// introduced in the standard library with Go 1.18. For example, the
// typeparams.Union type is an alias for go/types.Union, and the ForTypeSpec
-// function returns the value of the go/ast.TypeSpec.TypeParams field. At Go
-// versions older than 1.18 these helpers are implemented as stubs, allowing
-// users of this package to write code that handles generic constructs inline,
-// even if the Go version being used to compile does not support generics.
+// function returns the value of the go/ast.TypeSpec.TypeParams field.
//
// Additionally, this package contains common utilities for working with the
// new generic constructs, to supplement the standard library APIs. Notably,
@@ -28,8 +25,12 @@ import (
// Enabled reports whether type parameters are enabled in the current build
// environment.
+//
+// Deprecated: Type parameters are always enabled. Or use go fix (after go1.26).
+//
+//go:fix inline
func Enabled() bool {
- return enabled
+ return true
}
// UnpackIndexExpr extracts data from AST nodes that represent index
diff --git a/vendor/golang.org/x/exp/typeparams/normalize.go b/vendor/golang.org/x/exp/typeparams/normalize.go
index 6cf71f04..57370173 100644
--- a/vendor/golang.org/x/exp/typeparams/normalize.go
+++ b/vendor/golang.org/x/exp/typeparams/normalize.go
@@ -192,9 +192,3 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
}
return tset, nil
}
-
-// under is a facade for the go/types internal function of the same name. It is
-// used by typeterm.go.
-func under(t types.Type) types.Type {
- return t.Underlying()
-}
diff --git a/vendor/golang.org/x/exp/typeparams/termlist.go b/vendor/golang.org/x/exp/typeparams/termlist.go
index 6f88bfa9..a59a0a72 100644
--- a/vendor/golang.org/x/exp/typeparams/termlist.go
+++ b/vendor/golang.org/x/exp/typeparams/termlist.go
@@ -1,14 +1,15 @@
+// Code generated by copytermlist.go DO NOT EDIT.
+// Source: GOROOT/src/go/types/termlist.go
+
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Code generated by copytermlist.go DO NOT EDIT.
-
package typeparams
import (
- "bytes"
"go/types"
+ "strings"
)
// A termlist represents the type set represented by the union
@@ -22,15 +23,18 @@ type termlist []*term
// It is in normal form.
var allTermlist = termlist{new(term)}
+// termSep is the separator used between individual terms.
+const termSep = " | "
+
// String prints the termlist exactly (without normalization).
func (xl termlist) String() string {
if len(xl) == 0 {
return "∅"
}
- var buf bytes.Buffer
+ var buf strings.Builder
for i, x := range xl {
if i > 0 {
- buf.WriteString(" ∪ ")
+ buf.WriteString(termSep)
}
buf.WriteString(x.String())
}
@@ -97,15 +101,6 @@ func (xl termlist) norm() termlist {
return rl
}
-// If the type set represented by xl is specified by a single (non-𝓤) term,
-// singleType returns that type. Otherwise it returns nil.
-func (xl termlist) singleType() types.Type {
- if nl := xl.norm(); len(nl) == 1 {
- return nl[0].typ // if nl.isAll() then typ is nil, which is ok
- }
- return nil
-}
-
// union returns the union xl ∪ yl.
func (xl termlist) union(yl termlist) termlist {
return append(xl, yl...).norm()
diff --git a/vendor/golang.org/x/exp/typeparams/typeparams_go118.go b/vendor/golang.org/x/exp/typeparams/typeparams.go
similarity index 67%
rename from vendor/golang.org/x/exp/typeparams/typeparams_go118.go
rename to vendor/golang.org/x/exp/typeparams/typeparams.go
index 0b35449d..1b3bc8c9 100644
--- a/vendor/golang.org/x/exp/typeparams/typeparams_go118.go
+++ b/vendor/golang.org/x/exp/typeparams/typeparams.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build go1.18
-
package typeparams
import (
@@ -11,9 +9,11 @@ import (
"go/types"
)
-const enabled = true
-
// IndexListExpr is an alias for ast.IndexListExpr.
+//
+// Deprecated: Use [go/ast.IndexListExpr] instead.
+//
+//go:fix inline
type IndexListExpr = ast.IndexListExpr
// ForTypeSpec returns n.TypeParams.
@@ -33,115 +33,215 @@ func ForFuncType(n *ast.FuncType) *ast.FieldList {
}
// TypeParam is an alias for types.TypeParam
+//
+// Deprecated: Use [go/types.TypeParam] instead.
+//
+//go:fix inline
type TypeParam = types.TypeParam
// TypeParamList is an alias for types.TypeParamList
+//
+// Deprecated: Use [go/types.TypeParamList] instead.
+//
+//go:fix inline
type TypeParamList = types.TypeParamList
// TypeList is an alias for types.TypeList
+//
+// Deprecated: Use [go/types.TypeList] instead.
+//
+//go:fix inline
type TypeList = types.TypeList
// NewTypeParam calls types.NewTypeParam.
+//
+// Deprecated: Use [go/types.NewTypeParam] instead.
+//
+//go:fix inline
func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam {
return types.NewTypeParam(name, constraint)
}
// NewSignatureType calls types.NewSignatureType.
+//
+// Deprecated: Use [go/types.NewSignatureType] instead.
+//
+//go:fix inline
func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature {
return types.NewSignatureType(recv, recvTypeParams, typeParams, params, results, variadic)
}
// ForSignature returns sig.TypeParams()
+//
+// Deprecated: Use sig.TypeParams() instead.
+//
+//go:fix inline
func ForSignature(sig *types.Signature) *TypeParamList {
return sig.TypeParams()
}
// RecvTypeParams returns sig.RecvTypeParams().
+//
+// Deprecated: Use sig.RecvTypeParams() instead.
+//
+//go:fix inline
func RecvTypeParams(sig *types.Signature) *TypeParamList {
return sig.RecvTypeParams()
}
// IsComparable calls iface.IsComparable().
+//
+// Deprecated: Use iface.IsComparable() instead.
+//
+//go:fix inline
func IsComparable(iface *types.Interface) bool {
return iface.IsComparable()
}
// IsMethodSet calls iface.IsMethodSet().
+//
+// Deprecated: Use iface.IsMethodSet() instead.
+//
+//go:fix inline
func IsMethodSet(iface *types.Interface) bool {
return iface.IsMethodSet()
}
// IsImplicit calls iface.IsImplicit().
+//
+// Deprecated: Use iface.IsImplicit() instead.
+//
+//go:fix inline
func IsImplicit(iface *types.Interface) bool {
return iface.IsImplicit()
}
// MarkImplicit calls iface.MarkImplicit().
+//
+// Deprecated: Use iface.MarkImplicit() instead.
+//
+//go:fix inline
func MarkImplicit(iface *types.Interface) {
iface.MarkImplicit()
}
// ForNamed extracts the (possibly empty) type parameter object list from
// named.
+//
+// Deprecated: Use named.TypeParams() instead.
+//
+//go:fix inline
func ForNamed(named *types.Named) *TypeParamList {
return named.TypeParams()
}
// SetForNamed sets the type params tparams on n. Each tparam must be of
// dynamic type *types.TypeParam.
+//
+// Deprecated: Use n.SetTypeParams(...) instead.
+//
+//go:fix inline
func SetForNamed(n *types.Named, tparams []*TypeParam) {
n.SetTypeParams(tparams)
}
// NamedTypeArgs returns named.TypeArgs().
+//
+// Deprecated: Use named.TypeArgs() instead.
+//
+//go:fix inline
func NamedTypeArgs(named *types.Named) *TypeList {
return named.TypeArgs()
}
// NamedTypeOrigin returns named.Orig().
+//
+// Deprecated: Use named.Origin() instead.
+//
+//go:fix inline
func NamedTypeOrigin(named *types.Named) types.Type {
return named.Origin()
}
// Term is an alias for types.Term.
+//
+// Deprecated: Use [go/types.Term] instead.
+//
+//go:fix inline
type Term = types.Term
// NewTerm calls types.NewTerm.
+//
+// Deprecated: Use [go/types.NewTerm] instead.
+//
+//go:fix inline
func NewTerm(tilde bool, typ types.Type) *Term {
return types.NewTerm(tilde, typ)
}
// Union is an alias for types.Union
+//
+// Deprecated: Use [go/types.Union] instead.
+//
+//go:fix inline
type Union = types.Union
// NewUnion calls types.NewUnion.
+//
+// Deprecated: Use [go/types.NewUnion] instead.
+//
+//go:fix inline
func NewUnion(terms []*Term) *Union {
return types.NewUnion(terms)
}
// InitInstances initializes info to record information about type and function
// instances.
+//
+// Deprecated: Use info.Instances = make(...) instead.
+//
+//go:fix inline
func InitInstances(info *types.Info) {
info.Instances = make(map[*ast.Ident]types.Instance)
}
// Instance is an alias for types.Instance.
+//
+// Deprecated: Use [go/types.Instance] instead.
+//
+//go:fix inline
type Instance = types.Instance
// GetInstances returns info.Instances.
+//
+// Deprecated: Use info.Instances instead.
+//
+//go:fix inline
func GetInstances(info *types.Info) map[*ast.Ident]Instance {
return info.Instances
}
// Context is an alias for types.Context.
+//
+// Deprecated: Use [go/types.Context] instead.
+//
+//go:fix inline
type Context = types.Context
// NewContext calls types.NewContext.
+//
+// Deprecated: Use [go/types.NewContext] instead.
+//
+//go:fix inline
func NewContext() *Context {
return types.NewContext()
}
// Instantiate calls types.Instantiate.
+//
+// Deprecated: Use [go/types.Instantiate] instead.
+//
+//go:fix inline
func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
return types.Instantiate(ctxt, typ, targs, validate)
}
diff --git a/vendor/golang.org/x/exp/typeparams/typeparams_go117.go b/vendor/golang.org/x/exp/typeparams/typeparams_go117.go
deleted file mode 100644
index c1da7931..00000000
--- a/vendor/golang.org/x/exp/typeparams/typeparams_go117.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.18
-
-package typeparams
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-)
-
-const enabled = false
-
-func unsupported() {
- panic("type parameters are unsupported at this go version")
-}
-
-// IndexListExpr is a placeholder type, as type parameters are not supported at
-// this Go version. Its methods panic on use.
-type IndexListExpr struct {
- ast.Expr
- X ast.Expr // expression
- Lbrack token.Pos // position of "["
- Indices []ast.Expr // index expressions
- Rbrack token.Pos // position of "]"
-}
-
-func (*IndexListExpr) Pos() token.Pos { unsupported(); return token.NoPos }
-func (*IndexListExpr) End() token.Pos { unsupported(); return token.NoPos }
-
-// ForTypeSpec returns an empty field list, as type parameters on not supported
-// at this Go version.
-func ForTypeSpec(*ast.TypeSpec) *ast.FieldList {
- return nil
-}
-
-// ForFuncType returns an empty field list, as type parameters are not
-// supported at this Go version.
-func ForFuncType(*ast.FuncType) *ast.FieldList {
- return nil
-}
-
-// TypeParam is a placeholder type, as type parameters are not supported at
-// this Go version. Its methods panic on use.
-type TypeParam struct{ types.Type }
-
-func (*TypeParam) String() string { unsupported(); return "" }
-func (*TypeParam) Underlying() types.Type { unsupported(); return nil }
-func (*TypeParam) Index() int { unsupported(); return 0 }
-func (*TypeParam) Constraint() types.Type { unsupported(); return nil }
-func (*TypeParam) SetConstraint(types.Type) { unsupported() }
-func (*TypeParam) Obj() *types.TypeName { unsupported(); return nil }
-
-// TypeParamList is a placeholder for an empty type parameter list.
-type TypeParamList struct{}
-
-func (*TypeParamList) Len() int { return 0 }
-func (*TypeParamList) At(int) *TypeParam { unsupported(); return nil }
-
-// TypeList is a placeholder for an empty type list.
-type TypeList struct{}
-
-func (*TypeList) Len() int { return 0 }
-func (*TypeList) At(int) types.Type { unsupported(); return nil }
-
-// NewTypeParam is unsupported at this Go version, and panics.
-func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam {
- unsupported()
- return nil
-}
-
-// NewSignatureType calls types.NewSignature, panicking if recvTypeParams or
-// typeParams is non-empty.
-func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature {
- if len(recvTypeParams) != 0 || len(typeParams) != 0 {
- unsupported()
- }
- return types.NewSignature(recv, params, results, variadic)
-}
-
-// ForSignature returns an empty slice.
-func ForSignature(*types.Signature) *TypeParamList {
- return nil
-}
-
-// RecvTypeParams returns a nil slice.
-func RecvTypeParams(sig *types.Signature) *TypeParamList {
- return nil
-}
-
-// IsComparable returns false, as no interfaces are type-restricted at this Go
-// version.
-func IsComparable(*types.Interface) bool {
- return false
-}
-
-// IsMethodSet returns true, as no interfaces are type-restricted at this Go
-// version.
-func IsMethodSet(*types.Interface) bool {
- return true
-}
-
-// IsImplicit returns false, as no interfaces are implicit at this Go version.
-func IsImplicit(*types.Interface) bool {
- return false
-}
-
-// MarkImplicit does nothing, because this Go version does not have implicit
-// interfaces.
-func MarkImplicit(*types.Interface) {}
-
-// ForNamed returns an empty type parameter list, as type parameters are not
-// supported at this Go version.
-func ForNamed(*types.Named) *TypeParamList {
- return nil
-}
-
-// SetForNamed panics if tparams is non-empty.
-func SetForNamed(_ *types.Named, tparams []*TypeParam) {
- if len(tparams) > 0 {
- unsupported()
- }
-}
-
-// NamedTypeArgs returns nil.
-func NamedTypeArgs(*types.Named) *TypeList {
- return nil
-}
-
-// NamedTypeOrigin is the identity method at this Go version.
-func NamedTypeOrigin(named *types.Named) types.Type {
- return named
-}
-
-// Term holds information about a structural type restriction.
-type Term struct {
- tilde bool
- typ types.Type
-}
-
-func (m *Term) Tilde() bool { return m.tilde }
-func (m *Term) Type() types.Type { return m.typ }
-func (m *Term) String() string {
- pre := ""
- if m.tilde {
- pre = "~"
- }
- return pre + m.typ.String()
-}
-
-// NewTerm creates a new placeholder term type.
-func NewTerm(tilde bool, typ types.Type) *Term {
- return &Term{tilde, typ}
-}
-
-// Union is a placeholder type, as type parameters are not supported at this Go
-// version. Its methods panic on use.
-type Union struct{ types.Type }
-
-func (*Union) String() string { unsupported(); return "" }
-func (*Union) Underlying() types.Type { unsupported(); return nil }
-func (*Union) Len() int { return 0 }
-func (*Union) Term(i int) *Term { unsupported(); return nil }
-
-// NewUnion is unsupported at this Go version, and panics.
-func NewUnion(terms []*Term) *Union {
- unsupported()
- return nil
-}
-
-// InitInstances is a noop at this Go version.
-func InitInstances(*types.Info) {}
-
-// Instance is a placeholder type, as type parameters are not supported at this
-// Go version.
-type Instance struct {
- TypeArgs *TypeList
- Type types.Type
-}
-
-// GetInstances returns a nil map, as type parameters are not supported at this
-// Go version.
-func GetInstances(info *types.Info) map[*ast.Ident]Instance { return nil }
-
-// Context is a placeholder type, as type parameters are not supported at
-// this Go version.
-type Context struct{}
-
-// NewContext returns a placeholder Context instance.
-func NewContext() *Context {
- return &Context{}
-}
-
-// Instantiate is unsupported on this Go version, and panics.
-func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
- unsupported()
- return nil, nil
-}
diff --git a/vendor/golang.org/x/exp/typeparams/typeterm.go b/vendor/golang.org/x/exp/typeparams/typeterm.go
index 7350bb70..6b825729 100644
--- a/vendor/golang.org/x/exp/typeparams/typeterm.go
+++ b/vendor/golang.org/x/exp/typeparams/typeterm.go
@@ -1,9 +1,10 @@
+// Code generated by copytermlist.go DO NOT EDIT.
+// Source: GOROOT/src/go/types/typeterm.go
+
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Code generated by copytermlist.go DO NOT EDIT.
-
package typeparams
import "go/types"
@@ -119,7 +120,7 @@ func (x *term) includes(t types.Type) bool {
u := t
if x.tilde {
- u = under(u)
+ u = u.Underlying()
}
return types.Identical(x.typ, u)
}
@@ -159,11 +160,11 @@ func (x *term) disjoint(y *term) bool {
}
ux := x.typ
if y.tilde {
- ux = under(ux)
+ ux = ux.Underlying()
}
uy := y.typ
if x.tilde {
- uy = under(uy)
+ uy = uy.Underlying()
}
return !types.Identical(ux, uy)
}
diff --git a/vendor/golang.org/x/mod/modfile/read.go b/vendor/golang.org/x/mod/modfile/read.go
index 5b528c71..9e35e1ac 100644
--- a/vendor/golang.org/x/mod/modfile/read.go
+++ b/vendor/golang.org/x/mod/modfile/read.go
@@ -924,7 +924,7 @@ var (
moduleStr = []byte("module")
)
-// ModulePath returns the module path from the gomod file text.
+// ModulePath returns the module path from the go.mod file text.
// If it cannot find a module path, it returns an empty string.
// It is tolerant of unrelated problems in the go.mod file.
func ModulePath(mod []byte) string {
diff --git a/vendor/golang.org/x/mod/modfile/rule.go b/vendor/golang.org/x/mod/modfile/rule.go
index 9ab203b5..20ba825d 100644
--- a/vendor/golang.org/x/mod/modfile/rule.go
+++ b/vendor/golang.org/x/mod/modfile/rule.go
@@ -1477,7 +1477,7 @@ func (f *File) setRequireSeparateIndirect(req []*Require, simplify bool) {
// Delete requirements we don't want anymore.
// Update versions and indirect comments on requirements we want to keep.
// If a requirement is in last{Direct,Indirect}Block with the wrong
- // indirect marking after this, or if the requirement is in an single
+ // indirect marking after this, or if the requirement is in a single
// uncommented mixed block (oneFlatUncommentedBlock), move it to the
// correct block.
//
@@ -1537,7 +1537,7 @@ func (f *File) DropRequire(path string) error {
return nil
}
-// AddExclude adds a exclude statement to the mod file. Errors if the provided
+// AddExclude adds an exclude statement to the mod file. Errors if the provided
// version is not a canonical version string
func (f *File) AddExclude(path, vers string) error {
if err := checkCanonicalVersion(path, vers); err != nil {
@@ -1708,7 +1708,7 @@ func (f *File) AddIgnore(path string) error {
return nil
}
-// DropIgnore removes a ignore directive with the given path.
+// DropIgnore removes an ignore directive with the given path.
// It does nothing if no such ignore directive exists.
func (f *File) DropIgnore(path string) error {
for _, t := range f.Ignore {
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/fieldalignment/fieldalignment.go b/vendor/golang.org/x/tools/go/analysis/passes/fieldalignment/fieldalignment.go
index 53c74634..02791bc7 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/fieldalignment/fieldalignment.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/fieldalignment/fieldalignment.go
@@ -14,6 +14,7 @@ import (
"go/token"
"go/types"
"sort"
+ "strings"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
@@ -68,37 +69,66 @@ var Analyzer = &analysis.Analyzer{
func run(pass *analysis.Pass) (any, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
- nodeFilter := []ast.Node{
- (*ast.StructType)(nil),
- }
- inspect.Preorder(nodeFilter, func(node ast.Node) {
- var s *ast.StructType
- var ok bool
- if s, ok = node.(*ast.StructType); !ok {
- return
- }
- if tv, ok := pass.TypesInfo.Types[s]; ok {
- fieldalignment(pass, s, tv.Type.(*types.Struct))
+ for curStruct := range inspect.Root().Preorder((*ast.StructType)(nil)) {
+ s := curStruct.Node().(*ast.StructType)
+ // For every named struct defined as "type Name struct { ... }",
+ // the *ast.StructType node has a parent *ast.TypeSpec,
+ // which contains the struct's name in its Name field.
+ name := "struct" // (anonymous)
+ if spec, ok := curStruct.Parent().Node().(*ast.TypeSpec); ok {
+ name = spec.Name.Name
}
- })
+ fieldalignment(pass, s, name)
+ }
+
return nil, nil
}
-var unsafePointerTyp = types.Unsafe.Scope().Lookup("Pointer").(*types.TypeName).Type()
+func fieldalignment(pass *analysis.Pass, node *ast.StructType, name string) {
+ var (
+ sizes = &gcSizes{
+ wordSize: pass.TypesSizes.Sizeof(types.Typ[types.UnsafePointer]),
+ maxAlign: pass.TypesSizes.Alignof(types.Typ[types.UnsafePointer]),
+ }
-func fieldalignment(pass *analysis.Pass, node *ast.StructType, typ *types.Struct) {
- wordSize := pass.TypesSizes.Sizeof(unsafePointerTyp)
- maxAlign := pass.TypesSizes.Alignof(unsafePointerTyp)
+ typ = pass.TypesInfo.TypeOf(node).(*types.Struct)
+ optimal, indexes = optimalOrder(typ, sizes)
+
+ actualSize = sizes.sizeof(typ)
+ actualPtrs = sizes.ptrdata(typ)
+
+ optimalSize = sizes.sizeof(optimal)
+ optimalPtrs = sizes.ptrdata(optimal)
+ )
+
+ var message strings.Builder
+ if actualSize != optimalSize {
+ // Struct could be smaller.
+ // TODO(adonovan): IMHO the criterion should be "significantly smaller".
+ fmt.Fprintf(&message, "%s has size %d", name, actualSize)
+ actualClass := classSize(actualSize)
+ if actualClass == -1 {
+ actualClass = actualSize
+ fmt.Fprint(&message, " (uses global allocator)")
+ } else if actualClass != actualSize {
+ fmt.Fprintf(&message, " (allocator size class %d)", actualClass)
+ }
- s := gcSizes{wordSize, maxAlign}
- optimal, indexes := optimalOrder(typ, &s)
- optsz, optptrs := s.Sizeof(optimal), s.ptrdata(optimal)
+ fmt.Fprintf(&message, " but the optimal size is %d", optimalSize)
+ optimalClass := classSize(optimalSize)
+ if optimalClass == -1 {
+ optimalClass = optimalSize
+ } else if optimalClass != optimalSize {
+ fmt.Fprintf(&message, " (allocator size class %d)", optimalClass)
+ }
- var message string
- if sz := s.Sizeof(typ); sz != optsz {
- message = fmt.Sprintf("struct of size %d could be %d", sz, optsz)
- } else if ptrs := s.ptrdata(typ); ptrs != optptrs {
- message = fmt.Sprintf("struct with %d pointer bytes could be %d", ptrs, optptrs)
+ wastage := actualClass - optimalClass
+ if percentage := wastage * 100 / actualClass; percentage > 25 {
+ fmt.Fprintf(&message, " leading to a waste of %d bytes (%d%%)", wastage, percentage)
+ }
+ } else if actualPtrs != optimalPtrs {
+ // Struct could place pointers more efficiently for GC marking.
+ fmt.Fprintf(&message, "%s has %d leading bytes of pointer data but optimal value is %d", name, actualPtrs, optimalPtrs)
} else {
// Already optimal order.
return
@@ -151,7 +181,7 @@ func fieldalignment(pass *analysis.Pass, node *ast.StructType, typ *types.Struct
pass.Report(analysis.Diagnostic{
Pos: node.Pos(),
End: node.Pos() + token.Pos(len("struct")),
- Message: message,
+ Message: message.String(),
SuggestedFixes: []analysis.SuggestedFix{{
Message: "Rearrange fields",
TextEdits: []analysis.TextEdit{{
@@ -179,8 +209,8 @@ func optimalOrder(str *types.Struct, sizes *gcSizes) (*types.Struct, []int) {
ft := field.Type()
elems[i] = elem{
i,
- sizes.Alignof(ft),
- sizes.Sizeof(ft),
+ sizes.alignof(ft),
+ sizes.sizeof(ft),
sizes.ptrdata(ft),
}
}
@@ -240,40 +270,42 @@ func optimalOrder(str *types.Struct, sizes *gcSizes) (*types.Struct, []int) {
return types.NewStruct(fields, nil), indexes
}
-// Code below based on go/types.StdSizes.
+// gcSizes implements cmd/compile layout rules, providing ptrdata (GC
+// scanning limits) and trailing zero-size field padding not available
+// in [types.Sizes].
type gcSizes struct {
- WordSize int64
- MaxAlign int64
+ wordSize int64
+ maxAlign int64
}
-func (s *gcSizes) Alignof(T types.Type) int64 {
+func (s *gcSizes) alignof(T types.Type) int64 {
// For arrays and structs, alignment is defined in terms
// of alignment of the elements and fields, respectively.
switch t := T.Underlying().(type) {
case *types.Array:
// spec: "For a variable x of array type: unsafe.Alignof(x)
// is the same as unsafe.Alignof(x[0]), but at least 1."
- return s.Alignof(t.Elem())
+ return s.alignof(t.Elem())
case *types.Struct:
// spec: "For a variable x of struct type: unsafe.Alignof(x)
// is the largest of the values unsafe.Alignof(x.f) for each
// field f of x, but at least 1."
max := int64(1)
for i, nf := 0, t.NumFields(); i < nf; i++ {
- if a := s.Alignof(t.Field(i).Type()); a > max {
+ if a := s.alignof(t.Field(i).Type()); a > max {
max = a
}
}
return max
}
- a := s.Sizeof(T) // may be 0
+ a := s.sizeof(T) // may be 0
// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
if a < 1 {
return 1
}
- if a > s.MaxAlign {
- return s.MaxAlign
+ if a > s.maxAlign {
+ return s.maxAlign
}
return a
}
@@ -294,7 +326,7 @@ var basicSizes = [...]byte{
types.Complex128: 16,
}
-func (s *gcSizes) Sizeof(T types.Type) int64 {
+func (s *gcSizes) sizeof(T types.Type) int64 {
switch t := T.Underlying().(type) {
case *types.Basic:
k := t.Kind()
@@ -304,12 +336,12 @@ func (s *gcSizes) Sizeof(T types.Type) int64 {
}
}
if k == types.String {
- return s.WordSize * 2
+ return s.wordSize * 2
}
case *types.Array:
- return t.Len() * s.Sizeof(t.Elem())
+ return t.Len() * s.sizeof(t.Elem())
case *types.Slice:
- return s.WordSize * 3
+ return s.wordSize * 3
case *types.Struct:
nf := t.NumFields()
if nf == 0 {
@@ -320,7 +352,7 @@ func (s *gcSizes) Sizeof(T types.Type) int64 {
max := int64(1)
for i := range nf {
ft := t.Field(i).Type()
- a, sz := s.Alignof(ft), s.Sizeof(ft)
+ a, sz := s.alignof(ft), s.sizeof(ft)
if a > max {
max = a
}
@@ -331,9 +363,9 @@ func (s *gcSizes) Sizeof(T types.Type) int64 {
}
return align(o, max)
case *types.Interface:
- return s.WordSize * 2
+ return s.wordSize * 2
}
- return s.WordSize // catch-all
+ return s.wordSize // catch-all
}
// align returns the smallest y >= x such that y % a == 0.
@@ -347,13 +379,13 @@ func (s *gcSizes) ptrdata(T types.Type) int64 {
case *types.Basic:
switch t.Kind() {
case types.String, types.UnsafePointer:
- return s.WordSize
+ return s.wordSize
}
return 0
case *types.Chan, *types.Map, *types.Pointer, *types.Signature, *types.Slice:
- return s.WordSize
+ return s.wordSize
case *types.Interface:
- return 2 * s.WordSize
+ return 2 * s.wordSize
case *types.Array:
n := t.Len()
if n == 0 {
@@ -363,7 +395,7 @@ func (s *gcSizes) ptrdata(T types.Type) int64 {
if a == 0 {
return 0
}
- z := s.Sizeof(t.Elem())
+ z := s.sizeof(t.Elem())
return (n-1)*z + a
case *types.Struct:
nf := t.NumFields()
@@ -374,7 +406,7 @@ func (s *gcSizes) ptrdata(T types.Type) int64 {
var o, p int64
for i := range nf {
ft := t.Field(i).Type()
- a, sz := s.Alignof(ft), s.Sizeof(ft)
+ a, sz := s.alignof(ft), s.sizeof(ft)
fp := s.ptrdata(ft)
o = align(o, a)
if fp != 0 {
@@ -387,3 +419,16 @@ func (s *gcSizes) ptrdata(T types.Type) int64 {
panic("impossible")
}
+
+// Code below based on tools/gopls/internal/golang/hover.go
+
+// classSize reports the size class for a struct of the specified size, or -1 if unknown.
+// See GOROOT/src/runtime/msize.go for details.
+func classSize(size int64) int64 {
+ if size > 1<<15 {
+ return -1 // avoid allocation
+ }
+ // We assume that bytes.Clone doesn't trim,
+ // and reports the underlying size class
+ return int64(cap(bytes.Clone(make([]byte, size))))
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/inline/doc.go b/vendor/golang.org/x/tools/go/analysis/passes/inline/doc.go
new file mode 100644
index 00000000..fea596b9
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/passes/inline/doc.go
@@ -0,0 +1,130 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package inline defines an analyzer that inlines calls to functions
+and uses of constants marked with a "//go:fix inline" directive.
+
+# Analyzer inline
+
+inline: apply fixes based on 'go:fix inline' comment directives
+
+The inline analyzer inlines functions, constants, and type aliases
+that are marked for inlining.
+
+Use this command to apply (just) inline fixes en masse:
+
+ $ go fix -inline ./...
+
+## Functions
+
+Given a function that is marked for inlining, like this one:
+
+ //go:fix inline
+ func Square(x int) int { return Pow(x, 2) }
+
+this analyzer will recommend that calls to the function elsewhere, in the same
+or other packages, should be inlined.
+
+Inlining can be used to move off of a deprecated function:
+
+ // Deprecated: prefer Pow(x, 2).
+ //go:fix inline
+ func Square(x int) int { return Pow(x, 2) }
+
+It can also be used to move off of an obsolete package,
+as when the import path has changed or a higher major version is available:
+
+ package pkg
+
+ import pkg2 "pkg/v2"
+
+ //go:fix inline
+ func F() { pkg2.F(nil) }
+
+Replacing a call pkg.F() by pkg2.F(nil) can have no effect on the program,
+so this mechanism provides a low-risk way to update large numbers of calls.
+We recommend, where possible, expressing the old API in terms of the new one
+to enable automatic migration.
+
+The inliner takes care to avoid behavior changes, even subtle ones,
+such as changes to the order in which argument expressions are
+evaluated. When it cannot safely eliminate all parameter variables,
+it may introduce a "binding declaration" of the form
+
+ var params = args
+
+to evaluate argument expressions in the correct order and bind them to
+parameter variables. Since the resulting code transformation may be
+stylistically suboptimal, such inlinings may be disabled by specifying
+the -inline.allow_binding_decl=false flag to the analyzer driver.
+
+(In cases where it is not safe to "reduce" a call—that is, to replace
+a call f(x) by the body of function f, suitably substituted—the
+inliner machinery is capable of replacing f by a function literal,
+func(){...}(). However, the inline analyzer discards all such
+"literalizations" unconditionally, again on grounds of style.)
+
+## Constants
+
+Given a constant that is marked for inlining, like this one:
+
+ //go:fix inline
+ const Ptr = Pointer
+
+this analyzer will recommend that uses of Ptr should be replaced with Pointer.
+
+As with functions, inlining can be used to replace deprecated constants and
+constants in obsolete packages.
+
+A constant definition can be marked for inlining only if it refers to another
+named constant.
+
+The "//go:fix inline" comment must appear before a single const declaration on its own,
+as above; before a const declaration that is part of a group, as in this case:
+
+ const (
+ C = 1
+ //go:fix inline
+ Ptr = Pointer
+ )
+
+or before a group, applying to every constant in the group:
+
+ //go:fix inline
+ const (
+ Ptr = Pointer
+ Val = Value
+ )
+
+## Type aliases
+
+Similar to named constants, a type alias can also be marked for inlining:
+
+ //go:fix inline
+ type A = newpkg.A
+
+The analyzer will replace all references to the annotated type
+(A) by the type on the right-hand side of the declaration (newpkg.A).
+
+## Tests
+
+A use of a function, named constant, or type alias X from its
+dedicated test (TestX), is not inlined, since the purpose of the test
+is to exercise X itself, even if it is deprecated and other uses of it
+should be inlined.
+This applies to benchmarks and examples too, and follows the usual
+conventions of test function naming.
+
+Similarly, if the symbol X is declared in a file named foo.go, any use
+of it within a file named foo_test.go will also not be inlined.
+
+# Analyzer gofixdirective
+
+gofixdirective: validate uses of //go:fix comment directives
+
+The gofixdirective analyzer checks "//go:fix inline" directives for correctness.
+See the documentation for the gofix analyzer for more about "/go:fix inline".
+*/
+package inline
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/inline/inline.go b/vendor/golang.org/x/tools/go/analysis/passes/inline/inline.go
new file mode 100644
index 00000000..d16e0d0b
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/passes/inline/inline.go
@@ -0,0 +1,638 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inline
+
+import (
+ "fmt"
+ "go/ast"
+ "go/types"
+ "slices"
+ "strings"
+
+ _ "embed"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/analysis/passes/internal/gofixdirective"
+ "golang.org/x/tools/go/ast/edge"
+ "golang.org/x/tools/go/ast/inspector"
+ "golang.org/x/tools/go/types/typeutil"
+ "golang.org/x/tools/internal/analysis/analyzerutil"
+ typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
+ "golang.org/x/tools/internal/astutil"
+ "golang.org/x/tools/internal/moreiters"
+ "golang.org/x/tools/internal/packagepath"
+ "golang.org/x/tools/internal/refactor"
+ "golang.org/x/tools/internal/refactor/inline"
+ "golang.org/x/tools/internal/typesinternal"
+ "golang.org/x/tools/internal/typesinternal/typeindex"
+)
+
+//go:embed doc.go
+var doc string
+
+var Analyzer = &analysis.Analyzer{
+ Name: "inline",
+ Doc: analyzerutil.MustExtractDoc(doc, "inline"),
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inline",
+ Run: run,
+ FactTypes: []analysis.Fact{
+ (*goFixInlineFuncFact)(nil),
+ (*goFixInlineConstFact)(nil),
+ (*goFixInlineAliasFact)(nil),
+ },
+ Requires: []*analysis.Analyzer{
+ inspect.Analyzer,
+ typeindexanalyzer.Analyzer,
+ },
+}
+
+var (
+ allowBindingDecl bool
+ lazyEdits bool
+)
+
+func init() {
+ Analyzer.Flags.BoolVar(&allowBindingDecl, "allow_binding_decl", false,
+ "permit inlinings that require a 'var params = args' declaration")
+ Analyzer.Flags.BoolVar(&lazyEdits, "lazy_edits", false,
+ "compute edits lazily (only meaningful to gopls driver)")
+}
+
+// analyzer holds the state for this analysis.
+type analyzer struct {
+ pass *analysis.Pass
+ root inspector.Cursor
+ index *typeindex.Index
+ // memoization of repeated calls for same file.
+ fileContent map[string][]byte
+ // memoization of fact imports (nil => no fact)
+ inlinableFuncs map[*types.Func]*inline.Callee
+ inlinableConsts map[*types.Const]*goFixInlineConstFact
+ inlinableAliases map[*types.TypeName]*goFixInlineAliasFact
+}
+
+func run(pass *analysis.Pass) (any, error) {
+ a := &analyzer{
+ pass: pass,
+ root: pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Root(),
+ index: pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index),
+ fileContent: make(map[string][]byte),
+ inlinableFuncs: make(map[*types.Func]*inline.Callee),
+ inlinableConsts: make(map[*types.Const]*goFixInlineConstFact),
+ inlinableAliases: make(map[*types.TypeName]*goFixInlineAliasFact),
+ }
+ gofixdirective.Find(pass, a.root, a)
+ a.inline()
+ return nil, nil
+}
+
+// HandleFunc exports a fact for functions marked with go:fix.
+func (a *analyzer) HandleFunc(decl *ast.FuncDecl) {
+ content, err := a.readFile(decl)
+ if err != nil {
+ a.pass.Reportf(decl.Doc.Pos(), "invalid inlining candidate: cannot read source file: %v", err)
+ return
+ }
+ callee, err := inline.AnalyzeCallee(discard, a.pass.Fset, a.pass.Pkg, a.pass.TypesInfo, decl, content)
+ if err != nil {
+ a.pass.Reportf(decl.Doc.Pos(), "invalid inlining candidate: %v", err)
+ return
+ }
+ fn := a.pass.TypesInfo.Defs[decl.Name].(*types.Func)
+ a.pass.ExportObjectFact(fn, &goFixInlineFuncFact{callee})
+ a.inlinableFuncs[fn] = callee
+}
+
+// HandleAlias exports a fact for aliases marked with go:fix.
+func (a *analyzer) HandleAlias(spec *ast.TypeSpec) {
+ // Remember that this is an inlinable alias.
+ typ := &goFixInlineAliasFact{}
+ lhs := a.pass.TypesInfo.Defs[spec.Name].(*types.TypeName)
+ a.inlinableAliases[lhs] = typ
+ // Create a fact only if the LHS is exported and defined at top level.
+ // We create a fact even if the RHS is non-exported,
+ // so we can warn about uses in other packages.
+ if lhs.Exported() && typesinternal.IsPackageLevel(lhs) {
+ a.pass.ExportObjectFact(lhs, typ)
+ }
+}
+
+// HandleConst exports a fact for constants marked with go:fix.
+func (a *analyzer) HandleConst(nameIdent, rhsIdent *ast.Ident) {
+ lhs := a.pass.TypesInfo.Defs[nameIdent].(*types.Const)
+ rhs := a.pass.TypesInfo.Uses[rhsIdent].(*types.Const) // must be so in a well-typed program
+ con := &goFixInlineConstFact{
+ RHSName: rhs.Name(),
+ RHSPkgName: rhs.Pkg().Name(),
+ RHSPkgPath: rhs.Pkg().Path(),
+ }
+ if rhs.Pkg() == a.pass.Pkg {
+ con.rhsObj = rhs
+ }
+ a.inlinableConsts[lhs] = con
+ // Create a fact only if the LHS is exported and defined at top level.
+ // We create a fact even if the RHS is non-exported,
+ // so we can warn about uses in other packages.
+ if lhs.Exported() && typesinternal.IsPackageLevel(lhs) {
+ a.pass.ExportObjectFact(lhs, con)
+ }
+}
+
+// inline inlines each static call to an inlinable function
+// and each reference to an inlinable constant or type alias.
+func (a *analyzer) inline() {
+ for cur := range a.root.Preorder((*ast.CallExpr)(nil), (*ast.Ident)(nil)) {
+ switch n := cur.Node().(type) {
+ case *ast.CallExpr:
+ a.inlineCall(n, cur)
+
+ case *ast.Ident:
+ switch obj := a.pass.TypesInfo.Uses[n].(type) {
+ case *types.TypeName:
+ a.inlineAlias(obj, cur)
+ case *types.Const:
+ a.inlineConst(obj, cur)
+ }
+ }
+ }
+}
+
+// If call is a call to an inlinable func, suggest inlining its use at cur.
+func (a *analyzer) inlineCall(call *ast.CallExpr, cur inspector.Cursor) {
+ if fn := typeutil.StaticCallee(a.pass.TypesInfo, call); fn != nil {
+ // Inlinable?
+ callee, ok := a.inlinableFuncs[fn]
+ if !ok {
+ var fact goFixInlineFuncFact
+ if a.pass.ImportObjectFact(fn, &fact) {
+ callee = fact.Callee
+ a.inlinableFuncs[fn] = callee
+ }
+ }
+ if callee == nil {
+ return // nope
+ }
+
+ if a.withinTestOf(cur, fn) {
+ return // don't inline a function from within its own test
+ }
+
+ // Compute the edits.
+ //
+ // Ordinarily the analyzer reports a fix containing
+ // edits. However, the algorithm is somewhat expensive
+ // (unnecessarily so: see go.dev/issue/75773) so
+ // to reduce costs in gopls, we omit the edits,
+ // meaning that gopls must compute them on demand
+ // (based on the Diagnostic.Category) when they are
+ // requested via a code action.
+ //
+ // This does mean that the following categories of
+ // caller-dependent obstacles to inlining will be
+ // reported when the gopls user requests the fix,
+ // rather than by quietly suppressing the diagnostic:
+ // - shadowing problems
+ // - callee imports inaccessible "internal" packages
+ // - callee refers to nonexported symbols
+ // - callee uses too-new Go features
+ // - inlining call from a cgo file
+ var edits []analysis.TextEdit
+ if !lazyEdits {
+ // Inline the call.
+ caller := &inline.Caller{
+ Fset: a.pass.Fset,
+ Types: a.pass.Pkg,
+ Info: a.pass.TypesInfo,
+ File: astutil.EnclosingFile(cur),
+ Call: call,
+ CountUses: func(pkgname *types.PkgName) int {
+ return moreiters.Len(a.index.Uses(pkgname))
+ },
+ }
+ res, err := inline.Inline(caller, callee, &inline.Options{Logf: discard})
+ if err != nil {
+ a.pass.Reportf(call.Lparen, "%v", err)
+ return
+ }
+
+ if res.Literalized {
+ // Users are not fond of inlinings that literalize
+ // f(x) to func() { ... }(), so avoid them.
+ //
+ // (Unfortunately the inliner is very timid,
+ // and often literalizes when it cannot prove that
+ // reducing the call is safe; the user of this tool
+ // has no indication of what the problem is.)
+ return
+ }
+ if res.BindingDecl && !allowBindingDecl {
+ // When applying fix en masse, users are similarly
+ // unenthusiastic about inlinings that cannot
+ // entirely eliminate the parameters and
+ // insert a 'var params = args' declaration.
+ // The flag allows them to decline such fixes.
+ return
+ }
+ edits = res.Edits
+ }
+
+ a.pass.Report(analysis.Diagnostic{
+ Pos: call.Pos(),
+ End: call.End(),
+ Message: fmt.Sprintf("Call of %v should be inlined", callee),
+ Category: "inline_call", // keep consistent with gopls/internal/golang.fixInlineCall
+ SuggestedFixes: []analysis.SuggestedFix{{
+ Message: fmt.Sprintf("Inline call of %v", callee),
+ TextEdits: edits, // within gopls, this is nil => compute fix's edits lazily
+ }},
+ })
+ }
+}
+
+// withinTestOf reports whether curUse is within a dedicated test
+// function for the inlinable target symbol.
+// A call within its dedicated test should not be inlined.
+func (a *analyzer) withinTestOf(curUse inspector.Cursor, target types.Object) bool {
+ // x_test.go -> x
+ useFileBase, isTest := strings.CutSuffix(a.pass.Fset.File(curUse.Node().Pos()).Name(), "_test.go")
+ if !isTest {
+ return false // not a test file
+ }
+
+ // Suppress fixes for uses in x_test.go of target symbol defined in x.go (#79272).
+ if useFileBase == strings.TrimSuffix(a.pass.Fset.File(target.Pos()).Name(), ".go") {
+ return true
+ }
+
+ curFuncDecl, ok := moreiters.First(curUse.Enclosing((*ast.FuncDecl)(nil)))
+ if !ok {
+ return false // not in a function
+ }
+ funcDecl := curFuncDecl.Node().(*ast.FuncDecl)
+ if funcDecl.Recv != nil {
+ return false // not a test func
+ }
+ if strings.TrimSuffix(a.pass.Pkg.Path(), "_test") != target.Pkg().Path() {
+ return false // different package
+ }
+
+ // Computed expected SYMBOL portion of "ExampleSYMBOL_comment"
+ // for the target symbol. (Strictly, this convention applies
+ // only to Example functions.)
+ // TODO(adonovan): use a proper Test function parser.
+ symbol := target.Name()
+ if fn, ok := target.(*types.Func); ok {
+ if recv := fn.Signature().Recv(); recv != nil {
+ _, named := typesinternal.ReceiverNamed(recv)
+ symbol = named.Obj().Name() + "_" + symbol
+ }
+ }
+ fname := funcDecl.Name.Name
+ for _, pre := range []string{"Test", "Example", "Bench", "Fuzz"} {
+ if fname == pre+symbol || strings.HasPrefix(fname, pre+symbol+"_") {
+ return true // use of X within TestX
+ }
+ }
+
+ return false
+}
+
+// If tn is the TypeName of an inlinable alias, suggest inlining its use at cur.
+func (a *analyzer) inlineAlias(tn *types.TypeName, curId inspector.Cursor) {
+ inalias, ok := a.inlinableAliases[tn]
+ if !ok {
+ var fact goFixInlineAliasFact
+ if a.pass.ImportObjectFact(tn, &fact) {
+ inalias = &fact
+ a.inlinableAliases[tn] = inalias
+ }
+ }
+ if inalias == nil {
+ return // nope
+ }
+
+ if a.withinTestOf(curId, tn) {
+ return // don't inline a type alias from within its own test
+ }
+
+ alias := tn.Type().(*types.Alias)
+ // Remember the names of the alias's type params. When we check for shadowing
+ // later, we'll ignore these because they won't appear in the replacement text.
+ typeParamNames := map[*types.TypeName]bool{}
+ for tp := range alias.TypeParams().TypeParams() {
+ typeParamNames[tp.Obj()] = true
+ }
+ rhs := alias.Rhs()
+ curPath := a.pass.Pkg.Path()
+ curFile := astutil.EnclosingFile(curId)
+ id := curId.Node().(*ast.Ident)
+
+ // Find the complete identifier, which may take any of these forms:
+ // Id
+ // Id[T]
+ // Id[K, V]
+ // pkg.Id
+ // pkg.Id[T]
+ // pkg.Id[K, V]
+ var expr ast.Expr = id
+ if curId.ParentEdgeKind() == edge.SelectorExpr_Sel {
+ curId = curId.Parent()
+ expr = curId.Node().(ast.Expr)
+ }
+ // If expr is part of an IndexExpr or IndexListExpr, we'll need that node.
+ // Given C[int], TypeOf(C) is generic but TypeOf(C[int]) is instantiated.
+ switch curId.ParentEdgeKind() {
+ case edge.IndexExpr_X:
+ curId = curId.Parent()
+ expr = curId.Node().(*ast.IndexExpr)
+ case edge.IndexListExpr_X:
+ curId = curId.Parent()
+ expr = curId.Node().(*ast.IndexListExpr)
+ }
+
+ // Reject inlining of a type alias used to declare an embedded
+ // struct field if doing so would change the field's name.
+ if v, ok := a.pass.TypesInfo.Defs[id].(*types.Var); ok && v.Embedded() {
+ identicalName := false
+ // TODO(adonovan): should we allow a pointer (type A = *pkg.A)?
+ if rhs, ok := alias.Rhs().(*types.Named); ok {
+ identicalName = alias.Obj().Name() == rhs.Obj().Name()
+ }
+ if !identicalName {
+ // Type is embedded, inlining the alias will cause
+ // the field name to be changed, which might break
+ // programs in terms of backwards compatibility.
+ return
+ }
+ }
+
+ t := a.pass.TypesInfo.TypeOf(expr).(*types.Alias) // type of entire identifier
+ if targs := t.TypeArgs(); targs.Len() > 0 {
+ // Instantiate the alias with the type args from this use.
+ // For example, given type A = M[K, V], compute the type of the use
+ // A[int, Foo] as M[int, Foo].
+ // Don't validate instantiation: it can't panic unless we have a bug,
+ // in which case seeing the stack trace via telemetry would be helpful.
+ instAlias, _ := types.Instantiate(nil, alias, slices.Collect(targs.Types()), false)
+ rhs = instAlias.(*types.Alias).Rhs()
+ }
+
+ // We have an identifier A here (n), possibly qualified by a package
+ // identifier (sel.n), and an inlinable "type A = rhs" elsewhere.
+ //
+ // We can replace A with rhs if no name in rhs is shadowed at n's position,
+ // and every package in rhs is importable by the current package.
+ var (
+ importPrefixes = map[string]string{curPath: ""} // from pkg path to prefix
+ edits []analysis.TextEdit
+ )
+ for _, tn := range typenames(rhs) {
+ // Ignore the type parameters of the alias: they won't appear in the result.
+ if typeParamNames[tn] {
+ continue
+ }
+ var pkgPath, pkgName string
+ if pkg := tn.Pkg(); pkg != nil {
+ pkgPath = pkg.Path()
+ pkgName = pkg.Name()
+ }
+ if pkgPath == "" || pkgPath == curPath {
+ // The name is in the current package or the universe scope, so no import
+ // is required. Check that it is not shadowed (that is, that the type
+ // it refers to in rhs is the same one it refers to at n).
+ scope := a.pass.TypesInfo.Scopes[curFile].Innermost(id.Pos()) // n's scope
+ _, obj := scope.LookupParent(tn.Name(), id.Pos()) // what qn.name means in n's scope
+ if obj != tn {
+ return
+ }
+ } else if !packagepath.CanImport(a.pass.Pkg.Path(), pkgPath) {
+ // If this package can't see the package of this part of rhs, we can't inline.
+ return
+ } else if _, ok := importPrefixes[pkgPath]; !ok {
+ // Use AddImport to add pkgPath if it's not there already. Associate the prefix it assigns
+ // with the prefix it assigns
+ // with the package path for use by the TypeString qualifier below.
+ prefix, eds := refactor.AddImport(
+ a.pass.TypesInfo, curFile, pkgName, pkgPath, tn.Name(), id.Pos())
+ importPrefixes[pkgPath] = strings.TrimSuffix(prefix, ".")
+ edits = append(edits, eds...)
+ }
+ }
+
+ // To get the replacement text, render the alias RHS using the package prefixes
+ // we assigned above.
+ newText := types.TypeString(rhs, func(p *types.Package) string {
+ if p == a.pass.Pkg {
+ return ""
+ }
+ if prefix, ok := importPrefixes[p.Path()]; ok {
+ return prefix
+ }
+ panic(fmt.Sprintf("in %q, package path %q has no import prefix", rhs, p.Path()))
+ })
+ a.reportInline("type alias", "Type alias", expr, edits, newText)
+}
+
+// typenames returns the TypeNames for types within t (including t itself) that have
+// them: basic types, named types and alias types.
+// The same name may appear more than once.
+func typenames(t types.Type) []*types.TypeName {
+ var tns []*types.TypeName
+
+ var visit func(types.Type)
+ visit = func(t types.Type) {
+ if hasName, ok := t.(interface{ Obj() *types.TypeName }); ok {
+ tns = append(tns, hasName.Obj())
+ }
+ switch t := t.(type) {
+ case *types.Basic:
+ tns = append(tns, types.Universe.Lookup(t.Name()).(*types.TypeName))
+ case *types.Named:
+ for t := range t.TypeArgs().Types() {
+ visit(t)
+ }
+ case *types.Alias:
+ for t := range t.TypeArgs().Types() {
+ visit(t)
+ }
+ case *types.TypeParam:
+ tns = append(tns, t.Obj())
+ case *types.Pointer:
+ visit(t.Elem())
+ case *types.Slice:
+ visit(t.Elem())
+ case *types.Array:
+ visit(t.Elem())
+ case *types.Chan:
+ visit(t.Elem())
+ case *types.Map:
+ visit(t.Key())
+ visit(t.Elem())
+ case *types.Struct:
+ for field := range t.Fields() {
+ visit(field.Type())
+ }
+ case *types.Signature:
+ // Ignore the receiver: although it may be present, it has no meaning
+ // in a type expression.
+ // Ditto for receiver type params.
+ // Also, function type params cannot appear in a type expression.
+ if t.TypeParams() != nil {
+ panic("Signature.TypeParams in type expression")
+ }
+ visit(t.Params())
+ visit(t.Results())
+ case *types.Interface:
+ for etyp := range t.EmbeddedTypes() {
+ visit(etyp)
+ }
+ for method := range t.ExplicitMethods() {
+ visit(method.Type())
+ }
+ case *types.Tuple:
+ for v := range t.Variables() {
+ visit(v.Type())
+ }
+ case *types.Union:
+ panic("Union in type expression")
+ default:
+ panic(fmt.Sprintf("unknown type %T", t))
+ }
+ }
+
+ visit(t)
+
+ return tns
+}
+
+// If con is an inlinable constant, suggest inlining its use at cur.
+func (a *analyzer) inlineConst(con *types.Const, cur inspector.Cursor) {
+ incon, ok := a.inlinableConsts[con]
+ if !ok {
+ var fact goFixInlineConstFact
+ if a.pass.ImportObjectFact(con, &fact) {
+ incon = &fact
+ a.inlinableConsts[con] = incon
+ }
+ }
+ if incon == nil {
+ return // nope
+ }
+
+ if a.withinTestOf(cur, con) {
+ return // don't inline a type alias from within its own test
+ }
+
+ // If n is qualified by a package identifier, we'll need the full selector expression.
+ curFile := astutil.EnclosingFile(cur)
+ n := cur.Node().(*ast.Ident)
+
+ // We have an identifier A here (n), possibly qualified by a package identifier (sel.X,
+ // where sel is the parent of n), // and an inlinable "const A = B" elsewhere (incon).
+ // Consider replacing A with B.
+
+ // Check that the expression we are inlining (B) means the same thing
+ // (refers to the same object) in n's scope as it does in A's scope.
+ // If the RHS is not in the current package, AddImport will handle
+ // shadowing, so we only need to worry about when both expressions
+ // are in the current package.
+ if a.pass.Pkg.Path() == incon.RHSPkgPath {
+ // incon.rhsObj is the object referred to by B in the definition of A.
+ scope := a.pass.TypesInfo.Scopes[curFile].Innermost(n.Pos()) // n's scope
+ _, obj := scope.LookupParent(incon.RHSName, n.Pos()) // what "B" means in n's scope
+ if obj == nil {
+ // Should be impossible: if code at n can refer to the LHS,
+ // it can refer to the RHS.
+ panic(fmt.Sprintf("no object for inlinable const %s RHS %s", n.Name, incon.RHSName))
+ }
+ if obj != incon.rhsObj {
+ // "B" means something different here than at the inlinable const's scope.
+ return
+ }
+ } else if !packagepath.CanImport(a.pass.Pkg.Path(), incon.RHSPkgPath) {
+ // If this package can't see the RHS's package, we can't inline.
+ return
+ }
+ var (
+ importPrefix string
+ edits []analysis.TextEdit
+ )
+ if incon.RHSPkgPath != a.pass.Pkg.Path() {
+ importPrefix, edits = refactor.AddImport(
+ a.pass.TypesInfo, curFile, incon.RHSPkgName, incon.RHSPkgPath, incon.RHSName, n.Pos())
+ }
+ // If n is qualified by a package identifier, we'll need the full selector expression.
+ var expr ast.Expr = n
+ if cur.ParentEdgeKind() == edge.SelectorExpr_Sel {
+ expr = cur.Parent().Node().(ast.Expr)
+ }
+ a.reportInline("constant", "Constant", expr, edits, importPrefix+incon.RHSName)
+}
+
+// reportInline reports a diagnostic for fixing an inlinable name.
+func (a *analyzer) reportInline(kind, capKind string, ident ast.Expr, edits []analysis.TextEdit, newText string) {
+ edits = append(edits, analysis.TextEdit{
+ Pos: ident.Pos(),
+ End: ident.End(),
+ NewText: []byte(newText),
+ })
+ name := astutil.Format(a.pass.Fset, ident)
+ a.pass.Report(analysis.Diagnostic{
+ Pos: ident.Pos(),
+ End: ident.End(),
+ Message: fmt.Sprintf("%s %s should be inlined", capKind, name),
+ SuggestedFixes: []analysis.SuggestedFix{{
+ Message: fmt.Sprintf("Inline %s %s", kind, name),
+ TextEdits: edits,
+ }},
+ })
+}
+
+func (a *analyzer) readFile(node ast.Node) ([]byte, error) {
+ filename := a.pass.Fset.File(node.Pos()).Name()
+ content, ok := a.fileContent[filename]
+ if !ok {
+ var err error
+ content, err = a.pass.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ a.fileContent[filename] = content
+ }
+ return content, nil
+}
+
+// A goFixInlineFuncFact is exported for each function marked "//go:fix inline".
+// It holds information about the callee to support inlining.
+type goFixInlineFuncFact struct{ Callee *inline.Callee }
+
+func (f *goFixInlineFuncFact) String() string { return "goFixInline " + f.Callee.String() }
+func (*goFixInlineFuncFact) AFact() {}
+
+// A goFixInlineConstFact is exported for each constant marked "//go:fix inline".
+// It holds information about an inlinable constant. Gob-serializable.
+type goFixInlineConstFact struct {
+ // Information about "const LHSName = RHSName".
+ RHSName string
+ RHSPkgPath string
+ RHSPkgName string
+ rhsObj types.Object // for current package
+}
+
+func (c *goFixInlineConstFact) String() string {
+ return fmt.Sprintf("goFixInline const %q.%s", c.RHSPkgPath, c.RHSName)
+}
+
+func (*goFixInlineConstFact) AFact() {}
+
+// A goFixInlineAliasFact is exported for each type alias marked "//go:fix inline".
+// It holds no information; its mere existence demonstrates that an alias is inlinable.
+type goFixInlineAliasFact struct{}
+
+func (c *goFixInlineAliasFact) String() string { return "goFixInline alias" }
+func (*goFixInlineAliasFact) AFact() {}
+
+func discard(string, ...any) {}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/internal/gofixdirective/gofixdirective.go b/vendor/golang.org/x/tools/go/analysis/passes/internal/gofixdirective/gofixdirective.go
new file mode 100644
index 00000000..949df4bf
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/passes/internal/gofixdirective/gofixdirective.go
@@ -0,0 +1,143 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package gofixdirective searches for and validates go:fix directives. The
+// go/analysis/passes/inline package uses findgofix to perform inlining.
+// The go/analysis/passes/gofix package uses findgofix to check for problems
+// with go:fix directives.
+//
+// gofixdirective is separate from gofix to avoid depending on refactor/inline,
+// which is large.
+package gofixdirective
+
+// This package is tested by go/analysis/passes/inline.
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/ast/inspector"
+ internalastutil "golang.org/x/tools/internal/astutil"
+)
+
+// A Handler handles language entities with go:fix directives.
+type Handler interface {
+ HandleFunc(*ast.FuncDecl)
+ HandleAlias(*ast.TypeSpec)
+ HandleConst(name, rhs *ast.Ident)
+}
+
+// Find finds functions and constants annotated with an appropriate "//go:fix"
+// comment (the syntax proposed by #32816), and calls handler methods for each one.
+// h may be nil.
+func Find(pass *analysis.Pass, root inspector.Cursor, h Handler) {
+ for cur := range root.Preorder((*ast.FuncDecl)(nil), (*ast.GenDecl)(nil)) {
+ switch decl := cur.Node().(type) {
+ case *ast.FuncDecl:
+ findFunc(decl, h)
+
+ case *ast.GenDecl:
+ if decl.Tok != token.CONST && decl.Tok != token.TYPE {
+ continue
+ }
+ declInline := hasFixInline(decl.Doc)
+ // Accept inline directives on the entire decl as well as individual specs.
+ for _, spec := range decl.Specs {
+ switch spec := spec.(type) {
+ case *ast.TypeSpec: // Tok == TYPE
+ findAlias(pass, spec, declInline, h)
+
+ case *ast.ValueSpec: // Tok == CONST
+ findConst(pass, spec, declInline, h)
+ }
+ }
+ }
+ }
+}
+
+func findFunc(decl *ast.FuncDecl, h Handler) {
+ if !hasFixInline(decl.Doc) {
+ return
+ }
+ if h != nil {
+ h.HandleFunc(decl)
+ }
+}
+
+func findAlias(pass *analysis.Pass, spec *ast.TypeSpec, declInline bool, h Handler) {
+ if !declInline && !hasFixInline(spec.Doc) {
+ return
+ }
+ if !spec.Assign.IsValid() {
+ pass.Reportf(spec.Pos(), "invalid //go:fix inline directive: not a type alias")
+ return
+ }
+
+ // Disallow inlines of type expressions containing array types.
+ // Given an array type like [N]int where N is a named constant, go/types provides
+ // only the value of the constant as an int64. So inlining A in this code:
+ //
+ // const N = 5
+ // type A = [N]int
+ //
+ // would result in [5]int, breaking the connection with N.
+ for n := range ast.Preorder(spec.Type) {
+ if ar, ok := n.(*ast.ArrayType); ok && ar.Len != nil {
+ // Make an exception when the array length is a literal int.
+ if lit, ok := ast.Unparen(ar.Len).(*ast.BasicLit); ok && lit.Kind == token.INT {
+ continue
+ }
+ pass.Reportf(spec.Pos(), "invalid //go:fix inline directive: array types not supported")
+ return
+ }
+ }
+ if h != nil {
+ h.HandleAlias(spec)
+ }
+}
+
+func findConst(pass *analysis.Pass, spec *ast.ValueSpec, declInline bool, h Handler) {
+ specInline := hasFixInline(spec.Doc)
+ if declInline || specInline {
+ for i, nameIdent := range spec.Names {
+ if i >= len(spec.Values) {
+ // Possible following an iota.
+ break
+ }
+ var rhsIdent *ast.Ident
+ switch val := spec.Values[i].(type) {
+ case *ast.Ident:
+ // Constants defined with the predeclared iota cannot be inlined.
+ if pass.TypesInfo.Uses[val] == builtinIota {
+ pass.Reportf(val.Pos(), "invalid //go:fix inline directive: const value is iota")
+ return
+ }
+ rhsIdent = val
+ case *ast.SelectorExpr:
+ rhsIdent = val.Sel
+ default:
+ pass.Reportf(val.Pos(), "invalid //go:fix inline directive: const value is not the name of another constant")
+ return
+ }
+ if h != nil {
+ h.HandleConst(nameIdent, rhsIdent)
+ }
+ }
+ }
+}
+
+// hasFixInline reports the presence of a "//go:fix inline" directive
+// in the comments.
+func hasFixInline(cg *ast.CommentGroup) bool {
+ for _, d := range internalastutil.Directives(cg) {
+ if d.Tool == "go" && d.Name == "fix" && d.Args == "inline" {
+ return true
+ }
+ }
+ return false
+}
+
+var builtinIota = types.Universe.Lookup("iota")
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/any.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/any.go
index 579ab865..79e2802c 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/any.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/any.go
@@ -18,7 +18,7 @@ var AnyAnalyzer = &analysis.Analyzer{
Doc: analyzerutil.MustExtractDoc(doc, "any"),
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: runAny,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#any",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_any",
}
// The any pass replaces interface{} with go1.18's 'any'.
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/atomictypes.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/atomictypes.go
index 9df39fb2..6fd618f9 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/atomictypes.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/atomictypes.go
@@ -33,7 +33,7 @@ var AtomicTypesAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: runAtomic,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#atomictypes",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_atomictypes",
}
// TODO(mkalil): support the Pointer variants.
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/bloop.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/bloop.go
index ad45d744..d44c8567 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/bloop.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/bloop.go
@@ -32,7 +32,7 @@ var BLoopAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: bloop,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#bloop",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_bloop",
}
// bloop updates benchmarks that use "for range b.N", replacing it
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/doc.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/doc.go
index 260dd509..caf3df95 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/doc.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/doc.go
@@ -15,13 +15,16 @@ causing build breakage. However, these problems are generally
trivial to fix. We regard any modernizer whose fix changes program
behavior to have a serious bug and will endeavor to fix it.
-To apply all modernization fixes en masse, you can use the
+Since Go 1.26, the 'go fix' command has included the modernize suite,
+so to apply all modernization fixes en masse, you can use the
following command:
- $ go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix ./...
+ $ go fix ./...
+
+If you need to run a modernizer added or modified since the Go
+release, you can use this standalone command:
-(Do not use "go get -tool" to add gopls as a dependency of your
-module; gopls commands must be built from their release branch.)
+ $ go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix ./...
If the tool warns of conflicting fixes, you may need to run it more
than once until it has applied all fixes cleanly. This command is
@@ -182,6 +185,19 @@ unnecessary `x := x` statement.
This fix only applies to `range` loops.
+# Analyzer importcomment
+
+importcomment: remove obsolete comments specifying canonical import path
+
+The importcomment analyzer removes comments specifying the canonical
+import path, such as
+
+ package foo // import "example.com/foo"
+
+The go command enforced these comments in GOPATH mode via "go get", but
+ignores them in module mode, so they are obsolete once the package
+belongs to a module. The fix removes the comment.
+
# Analyzer mapsloop
mapsloop: replace explicit loops over maps with calls to maps package
@@ -331,6 +347,21 @@ No fix is offered in cases when the runtime type is dynamic, such as:
or when the operand has potential side effects.
+# Analyzer reflecttypeassert
+
+reflecttypeassert: replace v.Interface().(T) with reflect.TypeAssert[T](v)
+
+This analyzer suggests fixes to replace two-valued type assertions on
+the result of (reflect.Value).Interface with reflect.TypeAssert,
+introduced in go1.25, which avoids the intermediate allocation of an
+interface value, for example:
+
+ x, ok := v.Interface().(string) -> x, ok := reflect.TypeAssert[string](v)
+
+No fix is offered for single-valued assertions, since they panic when
+the assertion fails whereas reflect.TypeAssert does not. Nor is a fix
+offered for a type switch.
+
# Analyzer slicesbackward
slicesbackward: replace backward loops over slices with slices.Backward
@@ -353,6 +384,22 @@ the index and value variables are kept:
for i, v := range slices.Backward(s) { ... }
+# Analyzer slicesclip
+
+slicesclip: replace three-index slice expressions with slices.Clip
+
+The slicesclip analyzer suggests replacing a full slice expression of
+the form
+
+ x[:len(x):len(x)]
+
+which clips the capacity of a slice to its length, with the simpler
+and more readable
+
+ slices.Clip(x)
+
+added in Go 1.21.
+
# Analyzer slicescontains
slicescontains: replace loops with slices.Contains or slices.ContainsFunc
@@ -409,7 +456,7 @@ or its "for elem := range x.Len()" equivalent by a range loop over an
iterator offered by the same data type:
for elem := range x.All() {
- use(x.At(i)
+ use(elem)
}
where x is one of various well-known types in the standard library.
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/embedlit.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/embedlit.go
index da883d67..a30276a0 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/embedlit.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/embedlit.go
@@ -33,7 +33,7 @@ var EmbedLitAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: runEmbedLit,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#embedlit",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_embedlit",
}
// Go1.27 introduced the ability to directly access embedded struct fields.
@@ -84,14 +84,12 @@ func embedlitUnnest(pass *analysis.Pass, info *types.Info, curLit inspector.Curs
// Can't promote an unkeyed field; would result in a syntax error.
if kv, ok := elt.(*ast.KeyValueExpr); ok {
if innerLit := isEmbeddedFieldLit(info, compLitType, kv); innerLit != nil {
+ // Inv: len(innerLit.Elts) > 0. We skip empty struct literals.
// Emit edits to delete the unnecessary embedded field type specifier
// and its closing brace.
- closingPos := innerLit.Rbrace
- if len(innerLit.Elts) > 0 {
- // Delete any inner trailing commas or white space. Extra trailing commas
- // would result in invalid code.
- closingPos = innerLit.Elts[len(innerLit.Elts)-1].End()
- }
+ // Delete any inner trailing commas or white space. Extra trailing commas
+ // would result in invalid code.
+ closingPos := innerLit.Elts[len(innerLit.Elts)-1].End()
file := astutil.EnclosingFile(curLit)
// Enable modernizer only for Go1.27.
if !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_27) {
@@ -132,11 +130,11 @@ func embedlitUnnest(pass *analysis.Pass, info *types.Info, curLit inspector.Curs
}
// We can safely delete the entire line if the key value expression is
- // on a different line than the previous element, and the closing
- // brace of the inner literal is on a different line than its opening
- // brace.
+ // alone on its line: it starts on a new line relative to the previous
+ // element (prevLine < curLine), and the first element of the inner
+ // literal starts on a subsequent line.
if prevLine < curLine && curLine < tokFile.LineCount() && // (1-based)
- lineOf(innerLit.Lbrace) < lineOf(innerLit.Rbrace) {
+ lineOf(innerLit.Elts[0].Pos()) > curLine {
lineStart := tokFile.LineStart(curLine)
nextLineStart := tokFile.LineStart(curLine + 1)
// Check that there are no comments on the line we are going to delete.
@@ -211,15 +209,25 @@ func embedlitCombine(pass *analysis.Pass, index *typeindex.Index, info *types.In
case edge.AssignStmt_Rhs:
assign := curLit.Parent().Node().(*ast.AssignStmt)
// TODO(mkalil): Handle lhs forms that aren't idents, i.e. x.y[i] = T{...}.
- if id, ok := assign.Lhs[curLit.ParentEdgeIndex()].(*ast.Ident); ok {
+ // TODO(mkalil): Handle multi-assignments like t1, t2 := A{}, B{}
+ if len(assign.Lhs) != 1 {
+ return nil
+ }
+ if id, ok := assign.Lhs[0].(*ast.Ident); ok {
lhs = id
curStmt = curLit.Parent()
}
case edge.ValueSpec_Values:
spec := curLit.Parent().Node().(*ast.ValueSpec)
- lhs = spec.Names[curLit.ParentEdgeIndex()]
+ // TODO(mkalil): Handle multi-declarations like var (x = A{}; y = B{}) or var x, y = ...
+ if len(spec.Names) != 1 {
+ return nil
+ }
+ lhs = spec.Names[0]
if decl, ok := moreiters.First(curLit.Enclosing((*ast.DeclStmt)(nil))); ok {
- curStmt = decl
+ if gdecl, ok := decl.Node().(*ast.DeclStmt).Decl.(*ast.GenDecl); ok && len(gdecl.Specs) == 1 {
+ curStmt = decl
+ }
}
default:
return nil
@@ -233,7 +241,8 @@ func embedlitCombine(pass *analysis.Pass, index *typeindex.Index, info *types.In
tObj = info.ObjectOf(lhs)
// Marks the contiguous block of embedded field assign statements that will
// be moved into the struct initialization.
- firstStmt, lastStmt inspector.Cursor
+ firstStmt, lastStmt inspector.Cursor
+ hasEmbeddedSelection bool
)
stmtloop:
for {
@@ -264,6 +273,15 @@ stmtloop:
if obj != tObj {
break
}
+ // The selection is from an embedded field if it directly
+ // assigns an embedded struct field (t.B = B{...}) or if
+ // the length of the index path is greater than one.
+ seln := info.Selections[sel]
+ if v, ok := seln.Obj().(*types.Var); ok && v.Embedded() ||
+ len(seln.Index()) > 1 {
+ hasEmbeddedSelection = true
+ }
+
rhsCur := curStmt.ChildAt(edge.AssignStmt_Rhs, 0)
if uses(index, rhsCur, tObj) {
break
@@ -286,7 +304,8 @@ stmtloop:
lastStmt = curStmt
}
- if !firstStmt.Valid() {
+ if !firstStmt.Valid() || !hasEmbeddedSelection {
+ // We should not suggest a fix if none of the selections are from embedded fields.
return nil
}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/errorsastype.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/errorsastype.go
index 0e3f17fb..8a3f1c10 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/errorsastype.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/errorsastype.go
@@ -27,7 +27,7 @@ import (
var ErrorsAsTypeAnalyzer = &analysis.Analyzer{
Name: "errorsastype",
Doc: analyzerutil.MustExtractDoc(doc, "errorsastype"),
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#errorsastype",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_errorsastype",
Requires: []*analysis.Analyzer{typeindexanalyzer.Analyzer},
Run: errorsastype,
}
@@ -228,6 +228,9 @@ func canUseErrorsAsType(info *types.Info, index *typeindex.Index, curCall inspec
len(curDecl.Node().(*ast.GenDecl).Specs) != 1 {
return // not a simple "var v T" decl
}
+ if curDecl.ParentEdgeKind() != edge.DeclStmt_Decl {
+ return // package-level var, not a local declaration statement
+ }
// AsType requires that its type argument implements error.
// Reject if v does not implement error.
if !types.AssignableTo(v.Type(), errorType) {
@@ -239,5 +242,5 @@ func canUseErrorsAsType(info *types.Info, index *typeindex.Index, curCall inspec
// ...
// if errors.As(err, &v) { ... }
// with no uses of v outside the IfStmt.
- return v, curDecl.Parent(), curIfStmt // curDecl.Parent() is a DeclStmt
+ return v, curDecl.Parent(), curIfStmt
}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/fmtappendf.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/fmtappendf.go
index 82106541..d67b6ad1 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/fmtappendf.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/fmtappendf.go
@@ -30,7 +30,7 @@ var FmtAppendfAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: fmtappendf,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#fmtappendf",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_fmtappendf",
}
// The fmtappend function replaces []byte(fmt.Sprintf(...)) by
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/forvar.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/forvar.go
index ba54daeb..d79f1f9f 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/forvar.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/forvar.go
@@ -21,7 +21,7 @@ var ForVarAnalyzer = &analysis.Analyzer{
Doc: analyzerutil.MustExtractDoc(doc, "forvar"),
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: forvar,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#forvar",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_forvar",
}
// forvar offers to fix unnecessary copying of a for variable
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/importcomment.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/importcomment.go
new file mode 100644
index 00000000..de0f6879
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/importcomment.go
@@ -0,0 +1,69 @@
+// Copyright 2026 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modernize
+
+import (
+ "strings"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/internal/analysis/analyzerutil"
+)
+
+var importCommentAnalyzer = &analysis.Analyzer{
+ Name: "importcomment",
+ Doc: analyzerutil.MustExtractDoc(doc, "importcomment"),
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_importcomment",
+ Run: importcomment,
+}
+
+func importcomment(pass *analysis.Pass) (any, error) {
+ // Import path comments are ignored in module mode.
+ if pass.Module == nil {
+ return nil, nil
+ }
+
+ for _, file := range pass.Files {
+ // An import comment follows the package name on the same line.
+ pkgEnd := file.Name.End()
+ pkgLine := pass.Fset.Position(pkgEnd).Line
+ for _, c := range file.Comments {
+ if len(c.List) != 1 {
+ continue
+ }
+ if c.Pos() < pkgEnd {
+ continue
+ }
+ commentLine := pass.Fset.Position(c.Pos()).Line
+ if commentLine > pkgLine {
+ break // comments are sorted; the rest are on later lines
+ }
+ // Have: package p // comment
+ if !isImportComment(c.Text()) {
+ continue
+ }
+ pass.Report(analysis.Diagnostic{
+ Pos: c.Pos(),
+ End: c.End(),
+ Message: "canonical import path comment is ignored in module mode",
+ SuggestedFixes: []analysis.SuggestedFix{{
+ Message: "Remove obsolete import path comment",
+ TextEdits: []analysis.TextEdit{{
+ Pos: pkgEnd, // deletes the preceding space too
+ End: c.End(),
+ }},
+ }},
+ })
+ }
+ }
+
+ return nil, nil
+}
+
+// isImportComment reports whether text, a comment's content with its
+// markers removed, is a canonical import path comment, import "path".
+func isImportComment(text string) bool {
+ text = strings.TrimSpace(text)
+ return strings.HasPrefix(text, `import "`) && strings.HasSuffix(text, `"`)
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/maps.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/maps.go
index 7f3fd4e6..38d0f232 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/maps.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/maps.go
@@ -28,7 +28,7 @@ var MapsLoopAnalyzer = &analysis.Analyzer{
Doc: analyzerutil.MustExtractDoc(doc, "mapsloop"),
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: mapsloop,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#mapsloop",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_mapsloop",
}
// The mapsloop pass offers to simplify a loop of map insertions:
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/minmax.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/minmax.go
index 9fd86575..928fcf58 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/minmax.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/minmax.go
@@ -32,7 +32,7 @@ var MinMaxAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: minmax,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#minmax",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_minmax",
}
// The minmax pass replaces if/else statements with calls to min or max,
@@ -451,18 +451,3 @@ func checkMinMaxPattern(ifStmt *ast.IfStmt, falseResult ast.Expr, funcName, para
// Check if the sign matches the function name
return cond(sign < 0, "min", "max") == funcName
}
-
-// -- utils --
-
-func is[T any](x any) bool {
- _, ok := x.(T)
- return ok
-}
-
-func cond[T any](cond bool, t, f T) T {
- if cond {
- return t
- } else {
- return f
- }
-}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/modernize.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/modernize.go
index d7dfe558..9e950d7c 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/modernize.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/modernize.go
@@ -38,14 +38,17 @@ var Suite = []*analysis.Analyzer{
EmbedLitAnalyzer,
ErrorsAsTypeAnalyzer,
ForVarAnalyzer,
+ importCommentAnalyzer, // awaiting public symbol
MapsLoopAnalyzer,
MinMaxAnalyzer,
NewExprAnalyzer,
OmitZeroAnalyzer,
PlusBuildAnalyzer,
RangeIntAnalyzer,
+ reflectTypeAssertAnalyzer, // awaiting public symbol
ReflectTypeForAnalyzer,
slicesBackwardAnalyzer, // awaiting public symbol
+ slicesClipAnalyzer, // awaiting public symbol
SlicesContainsAnalyzer,
SlicesSortAnalyzer,
StdIteratorsAnalyzer,
@@ -121,7 +124,7 @@ func filesUsingGoVersion(pass *analysis.Pass, version string) iter.Seq[inspector
// specified standard packages or their dependencies.
func within(pass *analysis.Pass, pkgs ...string) bool {
path := pass.Pkg.Path()
- return packagepath.IsStdPackage(path) &&
+ return packagepath.MaybeStdPackage(path) &&
moreiters.Contains(stdlib.Dependencies(pkgs...), path)
}
@@ -135,6 +138,7 @@ var (
builtinMake = types.Universe.Lookup("make")
builtinNew = types.Universe.Lookup("new")
builtinNil = types.Universe.Lookup("nil")
+ builtinRecover = types.Universe.Lookup("recover")
builtinString = types.Universe.Lookup("string")
builtinTrue = types.Universe.Lookup("true")
byteSliceType = types.NewSlice(types.Typ[types.Byte])
@@ -184,3 +188,16 @@ func isLocal(obj types.Object) bool {
}
return depth >= 4
}
+
+func is[T any](x any) bool {
+ _, ok := x.(T)
+ return ok
+}
+
+func cond[T any](cond bool, t, f T) T {
+ if cond {
+ return t
+ } else {
+ return f
+ }
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/newexpr.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/newexpr.go
index c99d9c24..168c09fd 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/newexpr.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/newexpr.go
@@ -24,7 +24,7 @@ import (
var NewExprAnalyzer = &analysis.Analyzer{
Name: "newexpr",
Doc: analyzerutil.MustExtractDoc(doc, "newexpr"),
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#newexpr",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_newexpr",
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: run,
FactTypes: []analysis.Fact{&newLike{}},
@@ -53,7 +53,8 @@ func run(pass *analysis.Pass) (any, error) {
if sig.Results().Len() == 1 &&
is[*types.Pointer](sig.Results().At(0).Type()) && // => no iface conversion
sig.Params().Len() == 1 &&
- sig.Params().At(0) == v {
+ sig.Params().At(0) == v &&
+ !sig.Variadic() { // we can't safely transform a variadic function call, so skip them
// Export a fact for each one.
pass.ExportObjectFact(fn, &newLike{})
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/omitzero.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/omitzero.go
index 59ba9506..4d93f7f4 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/omitzero.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/omitzero.go
@@ -24,7 +24,7 @@ var OmitZeroAnalyzer = &analysis.Analyzer{
Doc: analyzerutil.MustExtractDoc(doc, "omitzero"),
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: omitzero,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#omitzero",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_omitzero",
}
// The omitzero pass searches for instances of "omitempty" in a json field tag on a
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/plusbuild.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/plusbuild.go
index 574ce0a8..09877f89 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/plusbuild.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/plusbuild.go
@@ -17,7 +17,7 @@ import (
var PlusBuildAnalyzer = &analysis.Analyzer{
Name: "plusbuild",
Doc: analyzerutil.MustExtractDoc(doc, "plusbuild"),
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#plusbuild",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_plusbuild",
Run: plusbuild,
}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/rangeint.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/rangeint.go
index f7cb965f..9cd76633 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/rangeint.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/rangeint.go
@@ -13,8 +13,6 @@ import (
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
- "golang.org/x/tools/go/ast/edge"
- "golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/go/types/typeutil"
"golang.org/x/tools/internal/analysis/analyzerutil"
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
@@ -33,7 +31,7 @@ var RangeIntAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: rangeint,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#rangeint",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_rangeint",
}
// rangeint offers a fix to replace a 3-clause 'for' loop:
@@ -112,7 +110,7 @@ func rangeint(pass *analysis.Pass) (any, error) {
// limit is a local or unexported global var.
// (An exported global may have uses we can't see.)
for cur := range typeindex.Uses(v) {
- if isScalarLvalue(info, cur) {
+ if typesinternal.IsAssignedOrAddressTaken(info, cur) {
// Limit var is assigned or address-taken.
continue nextLoop
}
@@ -161,7 +159,7 @@ func rangeint(pass *analysis.Pass) (any, error) {
// Reject if any is an l-value (assigned or address-taken):
// a "for range int" loop does not respect assignments to
// the loop variable.
- if isScalarLvalue(info, curId) {
+ if typesinternal.IsAssignedOrAddressTaken(info, curId) {
continue nextLoop
}
}
@@ -345,40 +343,3 @@ func rangeint(pass *analysis.Pass) (any, error) {
}
return nil, nil
}
-
-// isScalarLvalue reports whether the specified identifier is
-// address-taken or appears on the left side of an assignment.
-//
-// This function is valid only for scalars (x = ...),
-// not for aggregates (x.a[i] = ...)
-func isScalarLvalue(info *types.Info, curId inspector.Cursor) bool {
- // Unfortunately we can't simply use info.Types[e].Assignable()
- // as it is always true for a variable even when that variable is
- // used only as an r-value. So we must inspect enclosing syntax.
-
- cur := astutil.UnparenEnclosingCursor(curId)
-
- switch cur.ParentEdgeKind() {
- case edge.AssignStmt_Lhs:
- assign := cur.Parent().Node().(*ast.AssignStmt)
- if assign.Tok != token.DEFINE {
- return true // i = j or i += j
- }
- id := curId.Node().(*ast.Ident)
- if v, ok := info.Defs[id]; ok && v.Pos() != id.Pos() {
- return true // reassignment of i (i, j := 1, 2)
- }
- case edge.RangeStmt_Key:
- rng := cur.Parent().Node().(*ast.RangeStmt)
- if rng.Tok == token.ASSIGN {
- return true // "for k, v = range x" is like an AssignStmt to k, v
- }
- case edge.IncDecStmt_X:
- return true // i++, i--
- case edge.UnaryExpr_X:
- if cur.Parent().Node().(*ast.UnaryExpr).Op == token.AND {
- return true // &i
- }
- }
- return false
-}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/reflect.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/reflect.go
index 10fbdf8b..14446a13 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/reflect.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/reflect.go
@@ -30,7 +30,7 @@ var ReflectTypeForAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: reflecttypefor,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#reflecttypefor",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_reflecttypefor",
}
func reflecttypefor(pass *analysis.Pass) (any, error) {
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/reflecttypeassert.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/reflecttypeassert.go
new file mode 100644
index 00000000..ff41e43a
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/reflecttypeassert.go
@@ -0,0 +1,118 @@
+// Copyright 2026 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modernize
+
+import (
+ "go/ast"
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/edge"
+ "golang.org/x/tools/internal/analysis/analyzerutil"
+ typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
+ "golang.org/x/tools/internal/astutil"
+ "golang.org/x/tools/internal/refactor"
+ "golang.org/x/tools/internal/typesinternal"
+ "golang.org/x/tools/internal/typesinternal/typeindex"
+ "golang.org/x/tools/internal/versions"
+)
+
+var reflectTypeAssertAnalyzer = &analysis.Analyzer{
+ Name: "reflecttypeassert",
+ Doc: analyzerutil.MustExtractDoc(doc, "reflecttypeassert"),
+ Requires: []*analysis.Analyzer{
+ inspect.Analyzer,
+ typeindexanalyzer.Analyzer,
+ },
+ Run: reflecttypeassert,
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_reflecttypeassert",
+}
+
+func reflecttypeassert(pass *analysis.Pass) (any, error) {
+ var (
+ index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
+ info = pass.TypesInfo
+
+ valueInterface = index.Selection("reflect", "Value", "Interface")
+ )
+
+ for curCall := range index.Calls(valueInterface) {
+ call := curCall.Node().(*ast.CallExpr)
+ // Have: v.Interface()
+
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ continue // method expression reflect.Value.Interface(v)
+ }
+
+ // TypeAssert's argument must be a reflect.Value; a pointer
+ // receiver would need an explicit dereference in the rewrite.
+ if !typesinternal.IsTypeNamed(info.TypeOf(sel.X), "reflect", "Value") {
+ continue
+ }
+
+ // The call must be the operand of a type assertion
+ // (not a type switch, whose Type field is nil).
+ curOperand := astutil.UnparenEnclosingCursor(curCall)
+ if curOperand.ParentEdgeKind() != edge.TypeAssertExpr_X {
+ continue
+ }
+ curAssert := curOperand.Parent()
+ assert := curAssert.Node().(*ast.TypeAssertExpr)
+ if assert.Type == nil {
+ continue // type switch
+ }
+
+ // The assertion must be the sole RHS of a two-valued
+ // assignment, x, ok := v.Interface().(T), so that the
+ // rewrite preserves the "commaOK" semantics; a single-valued
+ // assertion panics on failure whereas TypeAssert does not.
+ curRhs := astutil.UnparenEnclosingCursor(curAssert)
+ if curRhs.ParentEdgeKind() != edge.AssignStmt_Rhs {
+ continue
+ }
+ assign := curRhs.Parent().Node().(*ast.AssignStmt)
+ if len(assign.Lhs) != 2 || len(assign.Rhs) != 1 ||
+ (assign.Tok != token.ASSIGN && assign.Tok != token.DEFINE) {
+ continue
+ }
+
+ file := astutil.EnclosingFile(curCall)
+ if !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_25) {
+ continue // TypeAssert requires go1.25
+ }
+
+ prefix, importEdits := refactor.AddImport(info, file, "reflect", "reflect", "TypeAssert", assert.Pos())
+
+ tstr := astutil.Format(pass.Fset, assert.Type)
+ pass.Report(analysis.Diagnostic{
+ Pos: assert.Pos(),
+ End: assert.End(),
+ Message: "Interface().(" + tstr + ") can be simplified using reflect.TypeAssert",
+ SuggestedFixes: []analysis.SuggestedFix{{
+ // v.Interface().(T) -> reflect.TypeAssert[T](v)
+ Message: "Replace Interface().(" + tstr + ") by reflect.TypeAssert[" + tstr + "]",
+ // Edit around sel.X instead of reformatting it, so its
+ // comments and spacing are preserved; only the type,
+ // which must move, is reformatted.
+ TextEdits: append(importEdits,
+ analysis.TextEdit{
+ Pos: assert.Pos(),
+ End: sel.X.Pos(),
+ NewText: []byte(prefix + "TypeAssert[" + tstr + "]("),
+ },
+ analysis.TextEdit{
+ Pos: sel.X.End(),
+ End: assert.End(),
+ NewText: []byte(")"),
+ },
+ ),
+ }},
+ })
+ }
+
+ return nil, nil
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/slices.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slices.go
index 6c8ea22b..4fb40a89 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/slices.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slices.go
@@ -27,7 +27,7 @@ var AppendClippedAnalyzer = &analysis.Analyzer{
Doc: analyzerutil.MustExtractDoc(doc, "appendclipped"),
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: appendclipped,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#appendclipped",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_appendclipped",
}
// The appendclipped pass offers to simplify a tower of append calls:
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesbackward.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesbackward.go
index 02cd30a2..c65a6c7e 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesbackward.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesbackward.go
@@ -19,6 +19,7 @@ import (
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
"golang.org/x/tools/internal/astutil"
"golang.org/x/tools/internal/refactor"
+ "golang.org/x/tools/internal/typesinternal"
"golang.org/x/tools/internal/typesinternal/typeindex"
"golang.org/x/tools/internal/versions"
)
@@ -32,7 +33,7 @@ var slicesBackwardAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: slicesbackward,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesbackward",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_slicesbackward",
}
// slicesbackward offers a fix to replace a manually-written backward loop:
@@ -128,7 +129,7 @@ func slicesbackward(pass *analysis.Pass) (any, error) {
// (e.g. &i before the loop).
bodyCur := curLoop.Child(loop.Body)
for curUse := range index.Uses(indexObj) {
- if !isScalarLvalue(info, curUse) {
+ if !typesinternal.IsAssignedOrAddressTaken(info, curUse) {
continue
}
if bodyCur.Contains(curUse) {
@@ -160,20 +161,25 @@ func slicesbackward(pass *analysis.Pass) (any, error) {
// If so, we also need to check whether s[i] is an lvalue. If we're
// mutating the slice or taking an element's address, a fix will not
// be offered.
+ // Modernization to "for _, v := range slices.Backward(s)" is unsafe if
+ // s[i] is mutated or address-taken (since v would be a local copy of
+ // the element so s[i] wouldn't get mutated).
+ // We don't need to worry about indirect selections (e.g. s[i].n++ where
+ // s is []*item) or indirect references like indexing a slice of slices.
if curUse.ParentEdgeKind() == edge.IndexExpr_Index {
- if isScalarLvalue(pass.TypesInfo, curUse.Parent()) {
+ curIdx := curUse.Parent()
+ if typesinternal.IsAssignedOrAddressTaken(info, curIdx) {
continue nextLoop
}
- idxCur := curUse.Parent()
- idxExpr := idxCur.Node().(*ast.IndexExpr)
+ idxExpr := curIdx.Node().(*ast.IndexExpr)
if astutil.EqualSyntax(idxExpr.X, sliceExpr) {
sliceIdxs++
// If the current statement is the first in the body of the form
// "name := s[i]", save it so we can use "name" as the value
// variable in slices.Backward. We can also remove the entire assign
// statement.
- if firstSliceIdxAssign == nil && idxCur.ParentEdgeKind() == edge.AssignStmt_Rhs {
- assignStmt := idxCur.Parent().Node().(*ast.AssignStmt)
+ if firstSliceIdxAssign == nil && curIdx.ParentEdgeKind() == edge.AssignStmt_Rhs {
+ assignStmt := curIdx.Parent().Node().(*ast.AssignStmt)
if len(assignStmt.Lhs) == 1 && assignStmt.Tok == token.DEFINE {
// The condition above implies that assignStmt.Lhs[0] is a valid
// identifier.
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesclip.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesclip.go
new file mode 100644
index 00000000..b08cbc69
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesclip.go
@@ -0,0 +1,81 @@
+// Copyright 2026 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modernize
+
+import (
+ "fmt"
+ "go/ast"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/types/typeutil"
+ "golang.org/x/tools/internal/analysis/analyzerutil"
+ "golang.org/x/tools/internal/astutil"
+ "golang.org/x/tools/internal/refactor"
+ "golang.org/x/tools/internal/typesinternal"
+ "golang.org/x/tools/internal/versions"
+)
+
+var slicesClipAnalyzer = &analysis.Analyzer{
+ Name: "slicesclip",
+ Doc: analyzerutil.MustExtractDoc(doc, "slicesclip"),
+ Requires: []*analysis.Analyzer{
+ inspect.Analyzer,
+ },
+ Run: slicesclip,
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_slicesclip",
+}
+
+func slicesclip(pass *analysis.Pass) (any, error) {
+ if within(pass, "slices", "runtime") {
+ return nil, nil
+ }
+ info := pass.TypesInfo
+
+ // isLenX reports whether e is a call len(x) where x is
+ // syntactically identical to the operand x of the slice expr.
+ isLenX := func(e, x ast.Expr) bool {
+ call, ok := e.(*ast.CallExpr)
+ if !ok || len(call.Args) != 1 {
+ return false
+ }
+ return typeutil.Callee(info, call) == builtinLen &&
+ astutil.EqualSyntax(call.Args[0], x)
+ }
+
+ for curFile := range filesUsingGoVersion(pass, versions.Go1_21) {
+ file := curFile.Node().(*ast.File)
+
+ for curSlice := range curFile.Preorder((*ast.SliceExpr)(nil)) {
+ slice := curSlice.Node().(*ast.SliceExpr)
+ _, ok := info.TypeOf(slice.X).Underlying().(*types.Slice) // in case x is an array/pointer to array
+ if !slice.Slice3 || slice.Low != nil || !ok {
+ continue
+ }
+
+ if isLenX(slice.High, slice.X) && isLenX(slice.Max, slice.X) && typesinternal.NoEffects(info, slice.X) {
+ // Have x[:len(x):len(x)] -> slices.Clip(x)
+ prefix, edits := refactor.AddImport(info, file, "slices", "slices", "Clip", slice.Pos())
+ sx := astutil.Format(pass.Fset, slice.X)
+ pass.Report(analysis.Diagnostic{
+ Pos: slice.Pos(),
+ End: slice.End(),
+ Message: "x[:len(x):len(x)] can be simplified using slices.Clip",
+ SuggestedFixes: []analysis.SuggestedFix{{
+ Message: fmt.Sprintf("Replace with slices.Clip(%s)", sx),
+ TextEdits: append(edits, analysis.TextEdit{
+ Pos: slice.Pos(),
+ End: slice.End(),
+ NewText: fmt.Appendf(nil, "%sClip(%s)", prefix, sx),
+ }),
+ }},
+ })
+ }
+ }
+ }
+
+ return nil, nil
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicescontains.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicescontains.go
index ed75e05e..b27be6fc 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicescontains.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicescontains.go
@@ -32,7 +32,7 @@ var SlicesContainsAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: slicescontains,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicescontains",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_slicescontains",
}
// The slicescontains pass identifies loops that can be replaced by a
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesdelete.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesdelete.go
index 7b3aa875..c623aede 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesdelete.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesdelete.go
@@ -25,7 +25,7 @@ var SlicesDeleteAnalyzer = &analysis.Analyzer{
Doc: analyzerutil.MustExtractDoc(doc, "slicesdelete"),
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: slicesdelete,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesdelete",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_slicesdelete",
}
// The slicesdelete pass attempts to replace instances of append(s[:i], s[i+k:]...)
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/sortslice.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/sortslice.go
index e22b8c55..08d86676 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/sortslice.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/sortslice.go
@@ -28,7 +28,7 @@ var SlicesSortAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: slicessort,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicessort",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_slicessort",
}
// The slicessort pass replaces sort.Slice(slice, less) with
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stditerators.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stditerators.go
index 19532686..25208863 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stditerators.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stditerators.go
@@ -28,7 +28,7 @@ var StdIteratorsAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: stditerators,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stditerators",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_stditerators",
}
// stditeratorsTable records std types that have legacy T.{Len,At}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsbuilder.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsbuilder.go
index 6aa9c881..ca1cc149 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsbuilder.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsbuilder.go
@@ -34,7 +34,7 @@ var StringsBuilderAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: stringsbuilder,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringbuilder",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_stringsbuilder",
}
// stringsbuilder replaces string += string in a loop by strings.Builder.
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscut.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscut.go
index ae93d4d3..daa6a678 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscut.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscut.go
@@ -35,7 +35,7 @@ var StringsCutAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: stringscut,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscut",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_stringscut",
}
// stringscut offers a fix to replace an occurrence of strings.Index{,Byte} with
@@ -513,9 +513,12 @@ func indexArgValid(info *types.Info, index *typeindex.Index, expr ast.Expr, afte
info.Types[expr.Fun].IsType() && // make sure this isn't a function that returns a byte slice
indexArgValid(info, index, expr.Args[0], afterPos) // check s in []byte(s)
case *ast.Ident:
- sObj := info.Uses[expr]
- sUses := index.Uses(sObj)
- return !hasModifyingUses(sUses, afterPos)
+ for use := range index.Uses(info.Uses[expr]) {
+ if typesinternal.IsAssignedOrAddressTaken(info, use) {
+ return false
+ }
+ }
+ return true
default:
// For now, skip instances where s or substr are not
// identifiers, basic lits, or call expressions of the form
@@ -612,30 +615,6 @@ func checkIdxUses(info *types.Info, uses iter.Seq[inspector.Cursor], s, substr a
return negative, nonnegative, beforeSlice, afterSlice
}
-// hasModifyingUses reports whether any of the uses involve potential
-// modifications. Uses involving assignments before the "afterPos" won't be
-// considered.
-func hasModifyingUses(uses iter.Seq[inspector.Cursor], afterPos token.Pos) bool {
- for curUse := range uses {
- ek := curUse.ParentEdgeKind()
- if ek == edge.AssignStmt_Lhs {
- if curUse.Node().Pos() <= afterPos {
- continue
- }
- // Any use on the LHS is a modifying use.
- return true
- } else if ek == edge.UnaryExpr_X &&
- curUse.Parent().Node().(*ast.UnaryExpr).Op == token.AND {
- // Modifying use because we might be passing the object by reference (an explicit &).
- // We can ignore the case where we have a method call on the expression (which
- // has an implicit &) because we know the type of s and substr are strings
- // which cannot have methods on them.
- return true
- }
- }
- return false
-}
-
// checkIdxComparison reports whether the check is equivalent to i < 0 or its negation, or neither.
// For equivalent to i >= 0, we only accept this exact BinaryExpr since
// expressions like i > 0 or i >= 1 make a stronger statement about the value of i.
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscutprefix.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscutprefix.go
index 11d33590..6e285456 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscutprefix.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscutprefix.go
@@ -31,7 +31,7 @@ var StringsCutPrefixAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: stringscutprefix,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscutprefix",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_stringscutprefix",
}
// stringscutprefix offers a fix to replace an if statement which
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsseq.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsseq.go
index d02a5323..064444dc 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsseq.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsseq.go
@@ -28,7 +28,7 @@ var StringsSeqAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: stringsseq,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringsseq",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_stringsseq",
}
// stringsseq offers a fix to replace a call to strings.Split with
@@ -117,6 +117,8 @@ func stringsseq(pass *analysis.Pass) (any, error) {
}
switch obj := typeutil.Callee(info, call); obj {
+ case nil:
+ // a conversion, not a call
case stringsSplit, stringsFields, bytesSplit, bytesFields:
oldFnName := obj.Name()
seqFnName := fmt.Sprintf("%sSeq", oldFnName)
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/testingcontext.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/testingcontext.go
index 93933052..da723647 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/testingcontext.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/testingcontext.go
@@ -33,7 +33,7 @@ var TestingContextAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: testingContext,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#testingcontext",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_testingcontext",
}
// The testingContext pass replaces calls to context.WithCancel from within
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/unsafefuncs.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/unsafefuncs.go
index 34c135ca..08198c9b 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/unsafefuncs.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/unsafefuncs.go
@@ -34,7 +34,7 @@ var unsafeFuncsAnalyzer = &analysis.Analyzer{
Doc: analyzerutil.MustExtractDoc(doc, "unsafefuncs"),
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: unsafefuncs,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#unsafefuncs",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_unsafefuncs",
}
func unsafefuncs(pass *analysis.Pass) (any, error) {
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/modernize/waitgroupgo.go b/vendor/golang.org/x/tools/go/analysis/passes/modernize/waitgroupgo.go
index 9af2d3bd..4bc88d0f 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/modernize/waitgroupgo.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/modernize/waitgroupgo.go
@@ -9,6 +9,7 @@ import (
"fmt"
"go/ast"
"go/printer"
+ "go/types"
"slices"
"golang.org/x/tools/go/analysis"
@@ -30,7 +31,7 @@ var WaitGroupGoAnalyzer = &analysis.Analyzer{
typeindexanalyzer.Analyzer,
},
Run: waitgroup,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#waitgroupgo",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_waitgroupgo",
}
// The waitgroupgo pass replaces old more complex code with
@@ -112,7 +113,7 @@ func waitgroup(pass *analysis.Pass) (any, error) {
astutil.EqualSyntax(ast.Unparen(deferStmt.Call.Fun).(*ast.SelectorExpr).X, addCallRecv) {
doneStmt = deferStmt // "defer wg.Done()"
- } else if lastStmt, ok := list[len(list)-1].(*ast.ExprStmt); ok {
+ } else if lastStmt, ok := list[len(list)-1].(*ast.ExprStmt); ok && cannotRecover(lit.Body, info) {
if doneCall, ok := lastStmt.X.(*ast.CallExpr); ok &&
typeutil.Callee(info, doneCall) == syncWaitGroupDone &&
astutil.EqualSyntax(ast.Unparen(doneCall.Fun).(*ast.SelectorExpr).X, addCallRecv) {
@@ -175,3 +176,44 @@ func waitgroup(pass *analysis.Pass) (any, error) {
}
return nil, nil
}
+
+// cannotRecover reports whether no panic arising in body can be
+// recovered. It conservatively treats a defer of anything but a
+// recover-free function literal (e.g. a named function) as able to recover.
+func cannotRecover(body *ast.BlockStmt, info *types.Info) bool {
+ res := true
+ ast.Inspect(body, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.DeferStmt:
+ lit, ok := ast.Unparen(n.Call.Fun).(*ast.FuncLit)
+ if !ok || containsRecover(lit.Body, info) {
+ res = false
+ }
+ // Each defer is fully handled here; don't descend into it.
+ return false
+ case *ast.FuncLit:
+ // Defers in nested functions cannot recover panics from this body.
+ return false
+ }
+ return true
+ })
+ return res
+}
+
+func containsRecover(body *ast.BlockStmt, info *types.Info) bool {
+ found := false
+ ast.Inspect(body, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.CallExpr:
+ if typeutil.Callee(info, n) == builtinRecover {
+ found = true
+ return false
+ }
+ case *ast.FuncLit:
+ // Recover calls in nested functions cannot recover panics from body.
+ return false
+ }
+ return true
+ })
+ return found
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/nilness/nilness.go b/vendor/golang.org/x/tools/go/analysis/passes/nilness/nilness.go
index 6f353968..18a100a8 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/nilness/nilness.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/nilness/nilness.go
@@ -7,6 +7,7 @@ package nilness
import (
_ "embed"
"fmt"
+ "go/ast"
"go/token"
"go/types"
@@ -14,6 +15,7 @@ import (
"golang.org/x/tools/go/analysis/passes/buildssa"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/internal/analysis/analyzerutil"
+ "golang.org/x/tools/internal/astutil"
"golang.org/x/tools/internal/typeparams"
)
@@ -37,6 +39,14 @@ func run(pass *analysis.Pass) (any, error) {
}
func runFunc(pass *analysis.Pass, fn *ssa.Function) {
+ // Skip cgo-generated functions annotated with
+ // //go:cgo_unsafe_args such as _cgo_cmalloc since
+ // they behave in magical ways not captured by the
+ // SSA representation, leading to false positives.
+ if hasCgoUnsafeArgs(fn) {
+ return
+ }
+
reportf := func(category string, pos token.Pos, format string, args ...any) {
// We ignore nil-checking ssa.Instructions
// that don't correspond to syntax.
@@ -495,3 +505,17 @@ func isRangeIndex(instr *ssa.IndexAddr) bool {
}
return false
}
+
+func hasCgoUnsafeArgs(fn *ssa.Function) bool {
+ for ; fn != nil; fn = fn.Parent() {
+ if decl, ok := fn.Syntax().(*ast.FuncDecl); ok && decl != nil {
+ for _, d := range astutil.Directives(decl.Doc) {
+ if d.Tool == "go" && d.Name == "cgo_unsafe_args" {
+ return true
+ }
+ }
+ }
+
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go
index f82d2eae..6573c3fc 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go
@@ -1184,15 +1184,6 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, name string) {
}
}
}
- if strings.HasSuffix(name, "ln") {
- // The last item, if a string, should not have a newline.
- arg = args[len(args)-1]
- if s, ok := stringConstantExpr(pass, arg); ok {
- if strings.HasSuffix(s, "\n") {
- pass.ReportRangef(call, "%s arg list ends with redundant newline", name)
- }
- }
- }
for _, arg := range args {
if isFunctionValue(pass, arg) {
pass.ReportRangef(call, "%s arg %s is a func value, not called", name, astutil.Format(pass.Fset, arg))
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/stdversion/stdversion.go b/vendor/golang.org/x/tools/go/analysis/passes/stdversion/stdversion.go
index d1fda880..3d44c4e8 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/stdversion/stdversion.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/stdversion/stdversion.go
@@ -15,6 +15,7 @@ import (
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
+ "golang.org/x/tools/internal/stdlib"
"golang.org/x/tools/internal/typesinternal"
"golang.org/x/tools/internal/versions"
)
@@ -64,8 +65,8 @@ func run(pass *analysis.Pass) (any, error) {
pkg *types.Package
version string
}
- memo := make(map[key]map[types.Object]string) // records symbol's minimum Go version
- disallowedSymbols := func(pkg *types.Package, version string) map[types.Object]string {
+ memo := make(map[key]map[types.Object]stdlib.Symbol)
+ disallowedSymbols := func(pkg *types.Package, version string) map[types.Object]stdlib.Symbol {
k := key{pkg, version}
disallowed, ok := memo[k]
if !ok {
@@ -98,20 +99,12 @@ func run(pass *analysis.Pass) (any, error) {
if fileVersion != "" {
if obj, ok := pass.TypesInfo.Uses[n]; ok && obj.Pkg() != nil {
disallowed := disallowedSymbols(obj.Pkg(), fileVersion)
- if minVersion, ok := disallowed[origin(obj)]; ok {
- // Some symbols are accessible before their release but
- // only with specific build tags unknown to us here.
- // Avoid false positives in such cases.
- // TODO(mkalil): move this check into typesinternal.TooNewStdSymbols.
- if obj.Pkg().Path() == "testing/synctest" && versions.AtLeast(fileVersion, "go1.24") {
- break // requires go1.24 && goexperiment.synctest || go1.25
- }
- noun := "module"
- if fileVersion != pkgVersion {
- noun = "file"
- }
+ if sym, ok := disallowed[origin(obj)]; ok {
pass.ReportRangef(n, "%s.%s requires %v or later (%s is %s)",
- obj.Pkg().Name(), obj.Name(), minVersion, noun, fileVersion)
+ obj.Pkg().Name(), sym.Name,
+ sym.Version,
+ cond(fileVersion != pkgVersion, "file", "module"),
+ fileVersion)
}
}
}
@@ -134,3 +127,11 @@ func origin(obj types.Object) types.Object {
}
return obj
}
+
+func cond[T any](cond bool, t, f T) T {
+ if cond {
+ return t
+ } else {
+ return f
+ }
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go b/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
index bd32d586..82968f46 100644
--- a/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
+++ b/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
@@ -16,7 +16,6 @@ package unusedresult
import (
_ "embed"
"go/ast"
- "go/token"
"go/types"
"sort"
"strings"
@@ -27,6 +26,7 @@ import (
"golang.org/x/tools/go/types/typeutil"
"golang.org/x/tools/internal/analysis/analyzerutil"
"golang.org/x/tools/internal/astutil"
+ "golang.org/x/tools/internal/typesinternal"
)
//go:embed doc.go
@@ -172,7 +172,7 @@ func run(pass *analysis.Pass) (any, error) {
}
// func() string
-var sigNoArgsStringResult = types.NewSignatureType(nil, nil, nil, nil, types.NewTuple(types.NewParam(token.NoPos, nil, "", types.Typ[types.String])), false)
+var sigNoArgsStringResult = types.NewSignatureType(nil, nil, nil, nil, typesinternal.TupleOf(types.Typ[types.String]), false)
type stringSetFlag map[string]bool
diff --git a/vendor/golang.org/x/tools/go/ast/inspector/cursor.go b/vendor/golang.org/x/tools/go/ast/inspector/cursor.go
index 239b10c4..1c482252 100644
--- a/vendor/golang.org/x/tools/go/ast/inspector/cursor.go
+++ b/vendor/golang.org/x/tools/go/ast/inspector/cursor.go
@@ -10,6 +10,7 @@ import (
"go/token"
"iter"
"reflect"
+ "strings"
"golang.org/x/tools/go/ast/edge"
)
@@ -110,6 +111,46 @@ func (c Cursor) String() string {
return reflect.TypeOf(c.Node()).String()
}
+// GoString returns a string describing the cursor's path from the
+// root, if any.
+func (c Cursor) GoString() string {
+ if !c.Valid() {
+ return "(invalid)"
+ }
+ if c.index < 0 {
+ return "(root)"
+ }
+ // e.g "File.Decls[1].(*ast.GenDecl).Specs[0].(*ast.TypeSpec)"
+ //
+ // In hindsight even the File node should have reported a
+ // virtual ParentEdge of (Root_Files, i) where i is the index
+ // among the files passed to NewInspector. Then the path would
+ // read "(root).Files[i]", etc; but we missed the boat.
+ var buf strings.Builder
+ buf.WriteString("File")
+ var visit func(Cursor)
+ visit = func(c Cursor) {
+ ek, idx := c.ParentEdge()
+ if ek == edge.Invalid {
+ return // File
+ }
+ visit(c.Parent())
+ fmt.Fprintf(&buf, ".%s", ek.FieldName())
+ if idx >= 0 {
+ fmt.Fprintf(&buf, "[%d]", idx)
+ }
+ ftype := ek.FieldType()
+ if idx >= 0 {
+ ftype = ftype.Elem() // []T -> T
+ }
+ if ftype.Kind() == reflect.Interface {
+ fmt.Fprintf(&buf, ".(%T)", c.Node())
+ }
+ }
+ visit(c)
+ return buf.String()
+}
+
// indices return the [start, end) half-open interval of event indices.
func (c Cursor) indices() (int32, int32) {
if c.index < 0 {
diff --git a/vendor/golang.org/x/tools/go/loader/loader.go b/vendor/golang.org/x/tools/go/loader/loader.go
index 9c5f7db1..3c9d4fe7 100644
--- a/vendor/golang.org/x/tools/go/loader/loader.go
+++ b/vendor/golang.org/x/tools/go/loader/loader.go
@@ -738,7 +738,9 @@ func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.Fil
// Preprocess CgoFiles and parse the outputs (sequentially).
if which == 'g' && bp.CgoFiles != nil {
+ ioLimit <- true
cgofiles, err := cgo.ProcessFiles(bp, conf.fset(), conf.DisplayPath, conf.ParserMode)
+ <-ioLimit
if err != nil {
errs = append(errs, err)
} else {
diff --git a/vendor/golang.org/x/tools/go/packages/visit.go b/vendor/golang.org/x/tools/go/packages/visit.go
index c546b1b6..06747a9d 100644
--- a/vendor/golang.org/x/tools/go/packages/visit.go
+++ b/vendor/golang.org/x/tools/go/packages/visit.go
@@ -5,11 +5,11 @@
package packages
import (
- "cmp"
"fmt"
"iter"
"os"
- "slices"
+
+ "golang.org/x/tools/internal/moremaps"
)
// Visit visits all the packages in the import graph whose roots are
@@ -40,7 +40,7 @@ func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {
seen[pkg] = true
if pre == nil || pre(pkg) {
- for _, imp := range sorted(pkg.Imports) { // for determinism
+ for _, imp := range moremaps.Sorted(pkg.Imports) { // for determinism
visit(imp)
}
}
@@ -88,7 +88,7 @@ func Postorder(pkgs []*Package) iter.Seq[*Package] {
visit = func(pkg *Package) bool {
if !seen[pkg] {
seen[pkg] = true
- for _, imp := range sorted(pkg.Imports) { // for determinism
+ for _, imp := range moremaps.Sorted(pkg.Imports) { // for determinism
if !visit(imp) {
return false
}
@@ -106,28 +106,3 @@ func Postorder(pkgs []*Package) iter.Seq[*Package] {
}
}
}
-
-// -- copied from golang.org.x/tools/gopls/internal/util/moremaps --
-
-// sorted returns an iterator over the entries of m in key order.
-func sorted[M ~map[K]V, K cmp.Ordered, V any](m M) iter.Seq2[K, V] {
- // TODO(adonovan): use maps.Sorted if proposal #68598 is accepted.
- return func(yield func(K, V) bool) {
- keys := keySlice(m)
- slices.Sort(keys)
- for _, k := range keys {
- if !yield(k, m[k]) {
- break
- }
- }
- }
-}
-
-// KeySlice returns the keys of the map M, like slices.Collect(maps.Keys(m)).
-func keySlice[M ~map[K]V, K comparable, V any](m M) []K {
- r := make([]K, 0, len(m))
- for k := range m {
- r = append(r, k)
- }
- return r
-}
diff --git a/vendor/golang.org/x/tools/go/ssa/builder.go b/vendor/golang.org/x/tools/go/ssa/builder.go
index 1669d80b..a663af8f 100644
--- a/vendor/golang.org/x/tools/go/ssa/builder.go
+++ b/vendor/golang.org/x/tools/go/ssa/builder.go
@@ -85,6 +85,7 @@ import (
"slices"
"golang.org/x/tools/internal/typeparams"
+ "golang.org/x/tools/internal/typesinternal"
"golang.org/x/tools/internal/versions"
)
@@ -124,7 +125,7 @@ var (
// The ssa:deferstack intrinsic returns the current function's defer stack.
vDeferStack = &Builtin{
name: "ssa:deferstack",
- sig: types.NewSignatureType(nil, nil, nil, nil, types.NewTuple(anonVar(tDeferStack)), false),
+ sig: types.NewSignatureType(nil, nil, nil, nil, typesinternal.TupleOf(tDeferStack), false),
}
)
@@ -1719,7 +1720,7 @@ func (b *builder) selectStmt(fn *Function, s *ast.SelectStmt, label *lblock) {
for _, st := range states {
if st.Dir == types.RecvOnly {
chtyp := typeparams.CoreType(fn.typ(st.Chan.Type())).(*types.Chan)
- vars = append(vars, anonVar(chtyp.Elem()))
+ vars = append(vars, newVar("", chtyp.Elem()))
}
}
sel.setType(types.NewTuple(vars...))
diff --git a/vendor/golang.org/x/tools/go/ssa/const.go b/vendor/golang.org/x/tools/go/ssa/const.go
index 91ed6f28..73a8213a 100644
--- a/vendor/golang.org/x/tools/go/ssa/const.go
+++ b/vendor/golang.org/x/tools/go/ssa/const.go
@@ -131,7 +131,9 @@ func nillable(t types.Type) bool {
return u != nil && nillable(u)
})
}
- switch t.Underlying().(type) {
+ switch t := t.Underlying().(type) {
+ case *types.Basic:
+ return t.Kind() == types.UnsafePointer
case *types.Pointer, *types.Slice, *types.Chan, *types.Map, *types.Signature:
return true
case *types.Interface:
diff --git a/vendor/golang.org/x/tools/go/ssa/methods.go b/vendor/golang.org/x/tools/go/ssa/methods.go
index 82faadeb..8de0785c 100644
--- a/vendor/golang.org/x/tools/go/ssa/methods.go
+++ b/vendor/golang.org/x/tools/go/ssa/methods.go
@@ -167,10 +167,18 @@ func (prog *Program) RuntimeTypes() []types.Type {
// eliminates the need to eagerly compute all the element
// types during SSA building.
var runtimeTypes []types.Type
- add := func(t types.Type) { runtimeTypes = append(runtimeTypes, t) }
var set typeutil.Map // for de-duping identical types
for t := range prog.makeInterfaceTypes {
- typesinternal.ForEachElement(&set, &prog.MethodSets, t, add)
+ typesinternal.ForEachElement(prog.MethodSets.MethodSet, t, func(t types.Type, access bool) bool {
+ if !access {
+ return false // inaccessible to reflection
+ }
+ seen, _ := set.Set(t, true).(bool)
+ if !seen {
+ runtimeTypes = append(runtimeTypes, t)
+ }
+ return seen
+ })
}
return runtimeTypes
diff --git a/vendor/golang.org/x/tools/go/ssa/util.go b/vendor/golang.org/x/tools/go/ssa/util.go
index 42f9621c..5dfca720 100644
--- a/vendor/golang.org/x/tools/go/ssa/util.go
+++ b/vendor/golang.org/x/tools/go/ssa/util.go
@@ -181,19 +181,13 @@ func newVar(name string, typ types.Type) *types.Var {
return types.NewParam(token.NoPos, nil, name, typ)
}
-// anonVar creates an anonymous 'var' for use in a types.Tuple.
-func anonVar(typ types.Type) *types.Var {
- return newVar("", typ)
-}
-
-var lenResults = types.NewTuple(anonVar(tInt))
+var lenResults = typesinternal.TupleOf(tInt)
// makeLen returns the len builtin specialized to type func(T)int.
func makeLen(T types.Type) *Builtin {
- lenParams := types.NewTuple(anonVar(T))
return &Builtin{
name: "len",
- sig: types.NewSignatureType(nil, nil, nil, lenParams, lenResults, false),
+ sig: types.NewSignatureType(nil, nil, nil, typesinternal.TupleOf(T), lenResults, false),
}
}
diff --git a/vendor/golang.org/x/tools/go/ssa/wrappers.go b/vendor/golang.org/x/tools/go/ssa/wrappers.go
index 6cadd049..fbb06743 100644
--- a/vendor/golang.org/x/tools/go/ssa/wrappers.go
+++ b/vendor/golang.org/x/tools/go/ssa/wrappers.go
@@ -26,6 +26,7 @@ import (
"go/types"
"golang.org/x/tools/internal/typeparams"
+ "golang.org/x/tools/internal/typesinternal"
)
// -- wrappers -----------------------------------------------------------
@@ -118,10 +119,12 @@ func (b *builder) buildWrapper(fn *Function) {
// For simple indirection wrappers, perform an informative nil-check:
// "value method (T).f called using nil *T pointer"
if len(indices) == 1 && !isPointer(recvType(fn.object)) {
+ params := typesinternal.TupleOf(fn.method.recv, tString, tString)
+ results := typesinternal.TupleOf(fn.method.recv)
var c Call
c.Call.Value = &Builtin{
name: "ssa:wrapnilchk",
- sig: types.NewSignatureType(nil, nil, nil, types.NewTuple(anonVar(fn.method.recv), anonVar(tString), anonVar(tString)), types.NewTuple(anonVar(fn.method.recv)), false),
+ sig: types.NewSignatureType(nil, nil, nil, params, results, false),
}
c.Call.Args = []Value{
v,
diff --git a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
index 0d6d0bce..9c7401c9 100644
--- a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
+++ b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
@@ -30,6 +30,7 @@ import (
"slices"
"strconv"
"strings"
+ "sync"
"golang.org/x/tools/internal/typesinternal"
)
@@ -126,7 +127,8 @@ func For(obj types.Object) (Path, error) {
// An Encoder amortizes the cost of encoding the paths of multiple objects.
// The zero value of an Encoder is ready to use.
type Encoder struct {
- pkgIndex map[*types.Package]*pkgIndex
+ pkgIndexMu sync.Mutex
+ pkgIndex map[*types.Package]*pkgIndex
}
// A traversal encapsulates the state of a single traversal of the object/type graph.
@@ -191,6 +193,8 @@ type pkgIndex struct {
// For returns the path to an object relative to its package,
// or an error if the object is not accessible from the package's Scope.
//
+// For is safe for concurrent use.
+//
// The For function guarantees to return a path only for the following objects:
// - package-level types
// - exported package-level non-types
@@ -320,6 +324,9 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
panic(obj)
}
+ enc.pkgIndexMu.Lock()
+ defer enc.pkgIndexMu.Unlock()
+
// 4. Search the object/type graph for the path to
// the var (field/param/result) or method.
ix, ok := enc.pkgIndex[pkg]
diff --git a/vendor/golang.org/x/tools/go/types/typeutil/callee.go b/vendor/golang.org/x/tools/go/types/typeutil/callee.go
index 3d24a8c6..b64a8f45 100644
--- a/vendor/golang.org/x/tools/go/types/typeutil/callee.go
+++ b/vendor/golang.org/x/tools/go/types/typeutil/callee.go
@@ -7,7 +7,8 @@ package typeutil
import (
"go/ast"
"go/types"
- _ "unsafe" // for linkname
+
+ "golang.org/x/tools/internal/typesinternal"
)
// Callee returns the named target of a function call, if any:
@@ -19,14 +20,7 @@ import (
// Note: for calls of instantiated functions and methods, Callee returns
// the corresponding generic function or method on the generic type.
func Callee(info *types.Info, call *ast.CallExpr) types.Object {
- obj := info.Uses[usedIdent(info, call.Fun)]
- if obj == nil {
- return nil
- }
- if _, ok := obj.(*types.TypeName); ok {
- return nil
- }
- return obj
+ return typesinternal.Callee(info, call)
}
// StaticCallee returns the target (function or method) of a static function
@@ -35,52 +29,5 @@ func Callee(info *types.Info, call *ast.CallExpr) types.Object {
// Note: for calls of instantiated functions and methods, StaticCallee returns
// the corresponding generic function or method on the generic type.
func StaticCallee(info *types.Info, call *ast.CallExpr) *types.Func {
- obj := info.Uses[usedIdent(info, call.Fun)]
- fn, _ := obj.(*types.Func)
- if fn == nil || interfaceMethod(fn) {
- return nil
- }
- return fn
-}
-
-// usedIdent is the implementation of [internal/typesinternal.UsedIdent].
-// It returns the identifier associated with e.
-// See typesinternal.UsedIdent for a fuller description.
-// This function should live in typesinternal, but cannot because it would
-// create an import cycle.
-//
-//go:linkname usedIdent golang.org/x/tools/go/types/typeutil.usedIdent
-func usedIdent(info *types.Info, e ast.Expr) *ast.Ident {
- if info.Types == nil || info.Uses == nil {
- panic("one of info.Types or info.Uses is nil; both must be populated")
- }
- // Look through type instantiation if necessary.
- switch d := ast.Unparen(e).(type) {
- case *ast.IndexExpr:
- if info.Types[d.Index].IsType() {
- e = d.X
- }
- case *ast.IndexListExpr:
- e = d.X
- }
-
- switch e := ast.Unparen(e).(type) {
- // info.Uses always has the object we want, even for selector expressions.
- // We don't need info.Selections.
- // See go/types/recording.go:recordSelection.
- case *ast.Ident:
- return e
- case *ast.SelectorExpr:
- return e.Sel
- }
- return nil
-}
-
-// interfaceMethod reports whether its argument is a method of an interface.
-// This function should live in typesinternal, but cannot because it would create an import cycle.
-//
-//go:linkname interfaceMethod golang.org/x/tools/go/types/typeutil.interfaceMethod
-func interfaceMethod(f *types.Func) bool {
- recv := f.Signature().Recv()
- return recv != nil && types.IsInterface(recv.Type())
+ return typesinternal.StaticCallee(info, call)
}
diff --git a/vendor/golang.org/x/tools/internal/analysis/analyzerutil/version.go b/vendor/golang.org/x/tools/internal/analysis/analyzerutil/version.go
index 700d53ef..60d7253c 100644
--- a/vendor/golang.org/x/tools/internal/analysis/analyzerutil/version.go
+++ b/vendor/golang.org/x/tools/internal/analysis/analyzerutil/version.go
@@ -38,7 +38,7 @@ func FileUsesGoVersion(pass *analysis.Pass, file *ast.File, version string) (_re
// The bootstrap rule does not cover tests,
// and some tests (e.g. debug/elf/file_test.go) rely on this.
pkgpath := pass.Pkg.Path()
- if packagepath.IsStdPackage(pkgpath) &&
+ if packagepath.MaybeStdPackage(pkgpath) &&
stdlib.IsBootstrapPackage(pkgpath) && // (excludes "*_test" external test packages)
!strings.HasSuffix(pass.Fset.File(file.Pos()).Name(), "_test.go") { // (excludes all tests)
fileVersion = stdlib.BootstrapVersion.String() // package must bootstrap
diff --git a/vendor/golang.org/x/tools/internal/astutil/free/free.go b/vendor/golang.org/x/tools/internal/astutil/free/free.go
new file mode 100644
index 00000000..2c4d2c4e
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/astutil/free/free.go
@@ -0,0 +1,418 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package free defines utilities for computing the free variables of
+// a syntax tree without type information. This is inherently
+// heuristic because of the T{f: x} ambiguity, in which f may or may
+// not be a lexical reference depending on whether T is a struct type.
+package free
+
+import (
+ "go/ast"
+ "go/token"
+)
+
+// Copied, with considerable changes, from go/parser/resolver.go
+// at af53bd2c03.
+
+// Names computes an approximation to the set of free names of the AST
+// at node n based solely on syntax.
+//
+// In the absence of composite literals, the set of free names is exact. Composite
+// literals introduce an ambiguity that can only be resolved with type information:
+// whether F is a field name or a value in `T{F: ...}`.
+// If includeComplitIdents is true, this function conservatively assumes
+// T is not a struct type, so freeishNames overapproximates: the resulting
+// set may contain spurious entries that are not free lexical references
+// but are references to struct fields.
+// If includeComplitIdents is false, this function assumes that T *is*
+// a struct type, so freeishNames underapproximates: the resulting set
+// may omit names that are free lexical references.
+//
+// TODO(adonovan): includeComplitIdents is a crude hammer: the caller
+// may have partial or heuristic information about whether a given T
+// is struct type. Replace includeComplitIdents with a hook to query
+// the caller.
+//
+// The code is based on go/parser.resolveFile, but heavily simplified. Crucial
+// differences are:
+// - Instead of resolving names to their objects, this function merely records
+// whether they are free.
+// - Labels are ignored: they do not refer to values.
+// - This is never called on ImportSpecs, so the function panics if it sees one.
+func Names(n ast.Node, includeComplitIdents bool) map[string]bool {
+ v := &freeVisitor{
+ free: make(map[string]bool),
+ includeComplitIdents: includeComplitIdents,
+ }
+ // Begin with a scope, even though n might not be a form that establishes a scope.
+ // For example, n might be:
+ // x := ...
+ // Then we need to add the first x to some scope.
+ v.openScope()
+ ast.Walk(v, n)
+ v.closeScope()
+ if v.scope != nil {
+ panic("unbalanced scopes")
+ }
+ return v.free
+}
+
+// A freeVisitor holds state for a free-name analysis.
+type freeVisitor struct {
+ scope *scope // the current innermost scope
+ free map[string]bool // free names seen so far
+ includeComplitIdents bool // include identifier key in composite literals
+}
+
+// scope contains all the names defined in a lexical scope.
+// It is like ast.Scope, but without deprecation warnings.
+type scope struct {
+ names map[string]bool
+ outer *scope
+}
+
+func (s *scope) defined(name string) bool {
+ for ; s != nil; s = s.outer {
+ if s.names[name] {
+ return true
+ }
+ }
+ return false
+}
+
+func (v *freeVisitor) Visit(n ast.Node) ast.Visitor {
+ switch n := n.(type) {
+
+ // Expressions.
+ case *ast.Ident:
+ v.use(n)
+
+ case *ast.FuncLit:
+ v.openScope()
+ defer v.closeScope()
+ v.walkFuncType(nil, n.Type)
+ v.walkBody(n.Body)
+
+ case *ast.SelectorExpr:
+ v.walk(n.X)
+ // Skip n.Sel: it cannot be free.
+
+ case *ast.StructType:
+ v.openScope()
+ defer v.closeScope()
+ v.walkFieldList(n.Fields)
+
+ case *ast.FuncType:
+ v.openScope()
+ defer v.closeScope()
+ v.walkFuncType(nil, n)
+
+ case *ast.CompositeLit:
+ v.walk(n.Type)
+ for _, e := range n.Elts {
+ if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+ if ident, _ := kv.Key.(*ast.Ident); ident != nil {
+ // It is not possible from syntax alone to know whether
+ // an identifier used as a composite literal key is
+ // a struct field (if n.Type is a struct) or a value
+ // (if n.Type is a map, slice or array).
+ if v.includeComplitIdents {
+ // Over-approximate by treating both cases as potentially
+ // free names.
+ v.use(ident)
+ } else {
+ // Under-approximate by ignoring potentially free names.
+ }
+ } else {
+ v.walk(kv.Key)
+ }
+ v.walk(kv.Value)
+ } else {
+ v.walk(e)
+ }
+ }
+
+ case *ast.InterfaceType:
+ v.openScope()
+ defer v.closeScope()
+ v.walkFieldList(n.Methods)
+
+ // Statements
+ case *ast.AssignStmt:
+ walkSlice(v, n.Rhs)
+ if n.Tok == token.DEFINE {
+ v.shortVarDecl(n.Lhs)
+ } else {
+ walkSlice(v, n.Lhs)
+ }
+
+ case *ast.LabeledStmt:
+ // Ignore labels.
+ v.walk(n.Stmt)
+
+ case *ast.BranchStmt:
+ // Ignore labels.
+
+ case *ast.BlockStmt:
+ v.openScope()
+ defer v.closeScope()
+ walkSlice(v, n.List)
+
+ case *ast.IfStmt:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.Init)
+ v.walk(n.Cond)
+ v.walk(n.Body)
+ v.walk(n.Else)
+
+ case *ast.CaseClause:
+ walkSlice(v, n.List)
+ v.openScope()
+ defer v.closeScope()
+ walkSlice(v, n.Body)
+
+ case *ast.SwitchStmt:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.Init)
+ v.walk(n.Tag)
+ v.walkBody(n.Body)
+
+ case *ast.TypeSwitchStmt:
+ v.openScope()
+ defer v.closeScope()
+ if n.Init != nil {
+ v.walk(n.Init)
+ }
+ v.walk(n.Assign)
+ // We can use walkBody here because we don't track label scopes.
+ v.walkBody(n.Body)
+
+ case *ast.CommClause:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.Comm)
+ walkSlice(v, n.Body)
+
+ case *ast.SelectStmt:
+ v.walkBody(n.Body)
+
+ case *ast.ForStmt:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.Init)
+ v.walk(n.Cond)
+ v.walk(n.Post)
+ v.walk(n.Body)
+
+ case *ast.RangeStmt:
+ v.openScope()
+ defer v.closeScope()
+ v.walk(n.X)
+ var lhs []ast.Expr
+ if n.Key != nil {
+ lhs = append(lhs, n.Key)
+ }
+ if n.Value != nil {
+ lhs = append(lhs, n.Value)
+ }
+ if len(lhs) > 0 {
+ if n.Tok == token.DEFINE {
+ v.shortVarDecl(lhs)
+ } else {
+ walkSlice(v, lhs)
+ }
+ }
+ v.walk(n.Body)
+
+ // Declarations
+ case *ast.GenDecl:
+ switch n.Tok {
+ case token.CONST, token.VAR:
+ for _, spec := range n.Specs {
+ spec := spec.(*ast.ValueSpec)
+ walkSlice(v, spec.Values)
+ v.walk(spec.Type)
+ v.declare(spec.Names...)
+ }
+
+ case token.TYPE:
+ for _, spec := range n.Specs {
+ spec := spec.(*ast.TypeSpec)
+ // Go spec: The scope of a type identifier declared inside a
+ // function begins at the identifier in the TypeSpec and ends
+ // at the end of the innermost containing block.
+ v.declare(spec.Name)
+ if spec.TypeParams != nil {
+ v.openScope()
+ defer v.closeScope()
+ v.walkTypeParams(spec.TypeParams)
+ }
+ v.walk(spec.Type)
+ }
+
+ case token.IMPORT:
+ panic("encountered import declaration in free analysis")
+ }
+
+ case *ast.FuncDecl:
+ if n.Recv == nil && n.Name.Name != "init" { // package-level function
+ v.declare(n.Name)
+ }
+ v.openScope()
+ defer v.closeScope()
+ v.walkTypeParams(n.Type.TypeParams)
+ v.walkFuncType(n.Recv, n.Type)
+ v.walkBody(n.Body)
+
+ default:
+ return v
+ }
+
+ return nil
+}
+
+func (v *freeVisitor) openScope() {
+ v.scope = &scope{map[string]bool{}, v.scope}
+}
+
+func (v *freeVisitor) closeScope() {
+ v.scope = v.scope.outer
+}
+
+func (v *freeVisitor) walk(n ast.Node) {
+ if n != nil {
+ ast.Walk(v, n)
+ }
+}
+
+func (v *freeVisitor) walkFuncType(recv *ast.FieldList, typ *ast.FuncType) {
+ // First use field types...
+ v.walkRecvFieldType(recv)
+ v.walkFieldTypes(typ.Params)
+ v.walkFieldTypes(typ.Results)
+
+ // ...then declare field names.
+ v.declareFieldNames(recv)
+ v.declareFieldNames(typ.Params)
+ v.declareFieldNames(typ.Results)
+}
+
+// A receiver field is not like a param or result field because
+// "func (recv R[T]) method()" uses R but declares T.
+func (v *freeVisitor) walkRecvFieldType(list *ast.FieldList) {
+ if list == nil {
+ return
+ }
+ for _, f := range list.List { // valid => len=1
+ typ := f.Type
+ if ptr, ok := typ.(*ast.StarExpr); ok {
+ typ = ptr.X
+ }
+
+ // Analyze receiver type as Base[Index, ...]
+ var (
+ base ast.Expr
+ indices []ast.Expr
+ )
+ switch typ := typ.(type) {
+ case *ast.IndexExpr: // B[T]
+ base, indices = typ.X, []ast.Expr{typ.Index}
+ case *ast.IndexListExpr: // B[K, V]
+ base, indices = typ.X, typ.Indices
+ default: // B
+ base = typ
+ }
+ for _, expr := range indices {
+ if id, ok := expr.(*ast.Ident); ok {
+ v.declare(id)
+ }
+ }
+ v.walk(base)
+ }
+}
+
+// walkTypeParams is like walkFieldList, but declares type parameters eagerly so
+// that they may be resolved in the constraint expressions held in the field
+// Type.
+func (v *freeVisitor) walkTypeParams(list *ast.FieldList) {
+ v.declareFieldNames(list)
+ v.walkFieldTypes(list) // constraints
+}
+
+func (v *freeVisitor) walkBody(body *ast.BlockStmt) {
+ if body == nil {
+ return
+ }
+ walkSlice(v, body.List)
+}
+
+func (v *freeVisitor) walkFieldList(list *ast.FieldList) {
+ if list == nil {
+ return
+ }
+ v.walkFieldTypes(list) // .Type may contain references
+ v.declareFieldNames(list) // .Names declares names
+}
+
+func (v *freeVisitor) shortVarDecl(lhs []ast.Expr) {
+ // Go spec: A short variable declaration may redeclare variables provided
+ // they were originally declared in the same block with the same type, and
+ // at least one of the non-blank variables is new.
+ //
+ // However, it doesn't matter to free analysis whether a variable is declared
+ // fresh or redeclared.
+ for _, x := range lhs {
+ // In a well-formed program each expr must be an identifier,
+ // but be forgiving.
+ if id, ok := x.(*ast.Ident); ok {
+ v.declare(id)
+ }
+ }
+}
+
+func walkSlice[S ~[]E, E ast.Node](r *freeVisitor, list S) {
+ for _, e := range list {
+ r.walk(e)
+ }
+}
+
+// walkFieldTypes resolves the types of the walkFieldTypes in list.
+// The companion method declareFieldList declares the names of the walkFieldTypes.
+func (v *freeVisitor) walkFieldTypes(list *ast.FieldList) {
+ if list != nil {
+ for _, f := range list.List {
+ v.walk(f.Type)
+ }
+ }
+}
+
+// declareFieldNames declares the names of the fields in list.
+// (Names in a FieldList always establish new bindings.)
+// The companion method resolveFieldList resolves the types of the fields.
+func (v *freeVisitor) declareFieldNames(list *ast.FieldList) {
+ if list != nil {
+ for _, f := range list.List {
+ v.declare(f.Names...)
+ }
+ }
+}
+
+// use marks ident as free if it is not in scope.
+func (v *freeVisitor) use(ident *ast.Ident) {
+ if s := ident.Name; s != "_" && !v.scope.defined(s) {
+ v.free[s] = true
+ }
+}
+
+// declare adds each non-blank ident to the current scope.
+func (v *freeVisitor) declare(idents ...*ast.Ident) {
+ for _, id := range idents {
+ if id.Name != "_" {
+ v.scope.names[id.Name] = true
+ }
+ }
+}
diff --git a/vendor/golang.org/x/tools/internal/imports/fix.go b/vendor/golang.org/x/tools/internal/imports/fix.go
index b99ea6c9..6aa1e27e 100644
--- a/vendor/golang.org/x/tools/internal/imports/fix.go
+++ b/vendor/golang.org/x/tools/internal/imports/fix.go
@@ -32,6 +32,7 @@ import (
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/gopathwalk"
+ "golang.org/x/tools/internal/modindex"
"golang.org/x/tools/internal/stdlib"
)
@@ -320,6 +321,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string {
// load reads in everything necessary to run a pass, and reports whether the
// file already has all the imports it needs. It fills in p.missingRefs with the
// file's missing symbols, if any, or removes unused imports if not.
+// This is called 3(!) times: self, otherFiles, loadRealPackageNames
func (p *pass) load(ctx context.Context) ([]*ImportFix, bool) {
p.knownPackages = map[string]*PackageInfo{}
p.missingRefs = References{}
@@ -577,6 +579,17 @@ func getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename st
}
func getFixesWithSource(ctx context.Context, fset *token.FileSet, f *ast.File, filename string, goroot string, logf func(string, ...any), source Source) ([]*ImportFix, error) {
+ // If there is an Index for the GOMODCACHE, remember that, and later make it so that the
+ // directory walk doesn't go into the module cache, since we already have all the information
+ var ix *modindex.Index
+ src, ok := source.(*ProcessEnvSource)
+ if ok {
+ var err error
+ if ix, err = modindex.Read(src.env.Env["GOMODCACHE"]); err != nil {
+ ix = nil // don't use it if there was an error
+ }
+ }
+
// This logic is defensively duplicated from getFixes.
abs, err := filepath.Abs(filename)
if err != nil {
@@ -635,6 +648,20 @@ func getFixesWithSource(ctx context.Context, fset *token.FileSet, f *ast.File, f
}
p.loadRealPackageNames = true
p.otherFiles = otherFiles
+ if ix != nil {
+ src, ok := p.source.(*ProcessEnvSource)
+ if ok {
+ // For safety, clone the env so that we don't modify the caller's env.
+ env := *src.env
+ env.Env = maps.Clone(src.env.Env)
+ src.env = &env
+ // avoid looking in the module cache, as we have the index instead:
+ // This makes a later call to newModuleresolver (from
+ // LoadPackageNames) produce a resolver that will not look
+ // in the module cache
+ src.env.Env["GOMODCACHE"] = ""
+ }
+ }
if fixes, done := p.load(ctx); done {
return fixes, nil
}
@@ -649,7 +676,7 @@ func getFixesWithSource(ctx context.Context, fset *token.FileSet, f *ast.File, f
// Go look for candidates in $GOPATH, etc. We don't necessarily load
// the real exports of sibling imports, so keep assuming their contents.
- if err := addExternalCandidates(ctx, p, p.missingRefs, filename); err != nil {
+ if err := addExternalCandidates(ctx, p, p.missingRefs, filename, ix); err != nil {
return nil, err
}
@@ -1184,7 +1211,7 @@ type scanCallback struct {
exportsLoaded func(pkg *pkg, exports []stdlib.Symbol)
}
-func addExternalCandidates(ctx context.Context, pass *pass, refs References, filename string) error {
+func addExternalCandidates(ctx context.Context, pass *pass, refs References, filename string, ix *modindex.Index) error {
ctx, done := event.Start(ctx, "imports.addExternalCandidates")
defer done()
@@ -1193,6 +1220,24 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs References, fil
return err
}
+ // Add candidates from the module cache.
+ if ix != nil {
+ for k, v := range refs {
+ for n := range v {
+ cands := ix.Lookup(k, n, false)
+ for _, cand := range cands {
+ x := &Result{
+ &ImportInfo{ImportPath: cand.ImportPath},
+ &PackageInfo{Name: cand.PkgName,
+ Exports: map[string]bool{cand.Name: true},
+ },
+ }
+ results = append(results, x)
+ }
+ }
+ }
+ }
+
for _, result := range results {
if result == nil {
continue
diff --git a/vendor/golang.org/x/tools/internal/imports/mod.go b/vendor/golang.org/x/tools/internal/imports/mod.go
index 76fae6a7..a05faf97 100644
--- a/vendor/golang.org/x/tools/internal/imports/mod.go
+++ b/vendor/golang.org/x/tools/internal/imports/mod.go
@@ -166,10 +166,7 @@ func newModuleResolver(e *ProcessEnv, moduleCacheCache *DirInfoCache) (*ModuleRe
}
}
- r.moduleCacheDir = gomodcacheForEnv(goenv)
- if r.moduleCacheDir == "" {
- return nil, fmt.Errorf("cannot resolve GOMODCACHE")
- }
+ r.moduleCacheDir = goenv["GOMODCACHE"]
sort.Slice(r.modsByModPath, func(i, j int) bool {
count := func(x int) int {
@@ -238,26 +235,6 @@ func newModuleResolver(e *ProcessEnv, moduleCacheCache *DirInfoCache) (*ModuleRe
return r, nil
}
-// gomodcacheForEnv returns the GOMODCACHE value to use based on the given env
-// map, which must have GOMODCACHE and GOPATH populated.
-//
-// TODO(rfindley): this is defensive refactoring.
-// 1. Is this even relevant anymore? Can't we just read GOMODCACHE.
-// 2. Use this to separate module cache scanning from other scanning.
-func gomodcacheForEnv(goenv map[string]string) string {
- if gmc := goenv["GOMODCACHE"]; gmc != "" {
- // golang/go#67156: ensure that the module cache is clean, since it is
- // assumed as a prefix to directories scanned by gopathwalk, which are
- // themselves clean.
- return filepath.Clean(gmc)
- }
- gopaths := filepath.SplitList(goenv["GOPATH"])
- if len(gopaths) == 0 {
- return ""
- }
- return filepath.Join(gopaths[0], "/pkg/mod")
-}
-
func (r *ModuleResolver) initAllMods() error {
stdout, err := r.env.invokeGo(context.TODO(), "list", "-m", "-e", "-json", "...")
if err != nil {
diff --git a/vendor/golang.org/x/tools/internal/imports/source_env.go b/vendor/golang.org/x/tools/internal/imports/source_env.go
index ec996c3c..272ae806 100644
--- a/vendor/golang.org/x/tools/internal/imports/source_env.go
+++ b/vendor/golang.org/x/tools/internal/imports/source_env.go
@@ -53,7 +53,7 @@ func (s *ProcessEnvSource) ResolveReferences(ctx context.Context, filename strin
found := make(map[string][]pkgDistance)
callback := &scanCallback{
rootFound: func(gopathwalk.Root) bool {
- return true // We want everything.
+ return true
},
dirFound: func(pkg *pkg) bool {
return pkgIsCandidate(filename, refs, pkg)
diff --git a/vendor/golang.org/x/tools/internal/modindex/directories.go b/vendor/golang.org/x/tools/internal/modindex/directories.go
new file mode 100644
index 00000000..9a963744
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/modindex/directories.go
@@ -0,0 +1,131 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modindex
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/mod/semver"
+ "golang.org/x/tools/internal/gopathwalk"
+)
+
+type directory struct {
+ path string // relative to GOMODCACHE
+ importPath string
+ version string // semantic version
+}
+
+// bestDirByImportPath returns the best directory for each import
+// path, where "best" means most recent semantic version. These import
+// paths are inferred from the GOMODCACHE-relative dir names in dirs.
+func bestDirByImportPath(dirs []string) (map[string]directory, error) {
+ dirsByPath := make(map[string]directory)
+ for _, dir := range dirs {
+ importPath, version, err := dirToImportPathVersion(dir)
+ if err != nil {
+ return nil, err
+ }
+ new := directory{
+ path: dir,
+ importPath: importPath,
+ version: version,
+ }
+ if old, ok := dirsByPath[importPath]; !ok || compareDirectory(new, old) < 0 {
+ dirsByPath[importPath] = new
+ }
+ }
+ return dirsByPath, nil
+}
+
+// compareDirectory defines an ordering of path@version directories,
+// by descending version, then by ascending path.
+func compareDirectory(x, y directory) int {
+ if sign := -semver.Compare(x.version, y.version); sign != 0 {
+ return sign // latest first
+ }
+ return strings.Compare(string(x.path), string(y.path))
+}
+
+// modCacheRegexp splits a relpathpath into module, module version, and package.
+var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`)
+
+// dirToImportPathVersion computes import path and semantic version
+// from a GOMODCACHE-relative directory name.
+func dirToImportPathVersion(dir string) (string, string, error) {
+ m := modCacheRegexp.FindStringSubmatch(string(dir))
+ // m[1] is the module path
+ // m[2] is the version major.minor.patch(-
-Click on a value or block to toggle highlighting of that value/block
-and its uses. (Values and blocks are highlighted by ID, and IDs of
-dead items may be reused, so not all highlights necessarily correspond
-to the clicked item.)
-
-
-
-Faded out values and blocks are dead code that has not been eliminated.
-
-
-
-Values printed in italics have a dependency cycle.
-
-
-
-CFG: Dashed edge is for unlikely branches. Blue color is for backward edges.
-Edge with a dot means that this edge follows the order in which blocks were laid out.
-
-
-
-`)
- w.WriteString("
")
- w.WriteString("
")
-}
-
-func (w *HTMLWriter) Close() {
- if w == nil {
- return
- }
- io.WriteString(w.w, "
")
- io.WriteString(w.w, "
")
- io.WriteString(w.w, "")
- io.WriteString(w.w, "")
- w.w.Close()
- fmt.Printf("dumped IR to %v\n", w.path)
-}
-
-// WriteFunc writes f in a column headed by title.
-// phase is used for collapsing columns and should be unique across the table.
-func (w *HTMLWriter) WriteFunc(phase, title string, f *Function) {
- if w == nil {
- return
- }
- w.WriteColumn(phase, title, "", funcHTML(f, phase, w.dot))
-}
-
-// WriteColumn writes raw HTML in a column headed by title.
-// It is intended for pre- and post-compilation log output.
-func (w *HTMLWriter) WriteColumn(phase, title, class, html string) {
- if w == nil {
- return
- }
- id := strings.Replace(phase, " ", "-", -1)
- // collapsed column
- w.Printf("
%v
", id, phase)
-
- if class == "" {
- w.Printf("
", id)
- } else {
- w.Printf("
", id, class)
- }
- w.WriteString("
" + title + "
")
- w.WriteString(html)
- w.WriteString("
")
-}
-
-func (w *HTMLWriter) Printf(msg string, v ...any) {
- if _, err := fmt.Fprintf(w.w, msg, v...); err != nil {
- log.Fatalf("%v", err)
- }
-}
-
-func (w *HTMLWriter) WriteString(s string) {
- if _, err := io.WriteString(w.w, s); err != nil {
- log.Fatalf("%v", err)
- }
-}
-
-func valueHTML(v Node) string {
- if v == nil {
- return "<nil>"
- }
- // TODO: Using the value ID as the class ignores the fact
- // that value IDs get recycled and that some values
- // are transmuted into other values.
- class := fmt.Sprintf("t%d", v.ID())
- var label string
- switch v := v.(type) {
- case *Function:
- label = v.RelString(nil)
- case *Builtin:
- label = v.Name()
- default:
- label = class
- }
- return fmt.Sprintf("%s", class, label)
-}
-
-func valueLongHTML(v Node) string {
- // TODO: Any intra-value formatting?
- // I'm wary of adding too much visual noise,
- // but a little bit might be valuable.
- // We already have visual noise in the form of punctuation
- // maybe we could replace some of that with formatting.
- var s strings.Builder
- s.WriteString(fmt.Sprintf("", v.ID()))
-
- linenumber := "(?)"
- if v.Pos().IsValid() {
- line := v.Parent().Prog.Fset.Position(v.Pos()).Line
- linenumber = fmt.Sprintf("(%d)", line, line)
- }
-
- s.WriteString(fmt.Sprintf("%s %s = %s", valueHTML(v), linenumber, opName(v)))
-
- if v, ok := v.(Value); ok {
- s.WriteString(" <" + html.EscapeString(v.Type().String()) + ">")
- }
-
- switch v := v.(type) {
- case *Parameter:
- s.WriteString(fmt.Sprintf(" {%s}", html.EscapeString(v.name)))
- case *BinOp:
- s.WriteString(fmt.Sprintf(" {%s}", html.EscapeString(v.Op.String())))
- case *UnOp:
- s.WriteString(fmt.Sprintf(" {%s}", html.EscapeString(v.Op.String())))
- case *Extract:
- name := v.Tuple.Type().(*types.Tuple).At(v.Index).Name()
- s.WriteString(fmt.Sprintf(" [%d] (%s)", v.Index, name))
- case *Field:
- st := v.X.Type().Underlying().(*types.Struct)
- // Be robust against a bad index.
- name := "?"
- if 0 <= v.Field && v.Field < st.NumFields() {
- name = st.Field(v.Field).Name()
- }
- s.WriteString(fmt.Sprintf(" [%d] (%s)", v.Field, name))
- case *FieldAddr:
- st := deref(v.X.Type()).Underlying().(*types.Struct)
- // Be robust against a bad index.
- name := "?"
- if 0 <= v.Field && v.Field < st.NumFields() {
- name = st.Field(v.Field).Name()
- }
-
- s.WriteString(fmt.Sprintf(" [%d] (%s)", v.Field, name))
- case *Recv:
- s.WriteString(fmt.Sprintf(" {%t}", v.CommaOk))
- case *Call:
- if v.Common().IsInvoke() {
- s.WriteString(fmt.Sprintf(" {%s}", html.EscapeString(v.Common().Method.FullName())))
- }
- case *Const:
- if v.Value == nil {
- s.WriteString(" {<nil>}")
- } else {
- s.WriteString(fmt.Sprintf(" {%s}", html.EscapeString(v.Value.String())))
- }
- case *Sigma:
- s.WriteString(fmt.Sprintf(" [#%s]", v.From))
- }
- for _, a := range v.Operands(nil) {
- s.WriteString(fmt.Sprintf(" %s", valueHTML(*a)))
- }
- if v, ok := v.(Instruction); ok {
- s.WriteString(fmt.Sprintf(" (%s)", v.Comment()))
- }
-
- // OPT(dh): we're calling namedValues many times on the same function.
- allNames := namedValues(v.Parent())
- var names []string
- for name, values := range allNames {
- for _, value := range values {
- if v == value {
- names = append(names, name.Name())
- break
- }
- }
- }
- if len(names) != 0 {
- s.WriteString(" (" + strings.Join(names, ", ") + ")")
- }
-
- s.WriteString("")
- return s.String()
-}
-
-func blockHTML(b *BasicBlock) string {
- // TODO: Using the value ID as the class ignores the fact
- // that value IDs get recycled and that some values
- // are transmuted into other values.
- s := html.EscapeString(b.String())
- return fmt.Sprintf("%s", s, s)
-}
-
-func blockLongHTML(b *BasicBlock) string {
- var kind string
- var term Instruction
- if len(b.Instrs) > 0 {
- term = b.Control()
- kind = opName(term)
- }
- // TODO: improve this for HTML?
- var s strings.Builder
- s.WriteString(fmt.Sprintf("%s", b.Index, kind))
-
- if term != nil {
- ops := term.Operands(nil)
- if len(ops) > 0 {
- var ss []string
- for _, op := range ops {
- ss = append(ss, valueHTML(*op))
- }
- s.WriteString(" " + strings.Join(ss, ", "))
- }
- }
- if len(b.Succs) > 0 {
- s.WriteString(" →") // right arrow
- for _, c := range b.Succs {
- s.WriteString(" " + blockHTML(c))
- }
- }
- return s.String()
-}
-
-func funcHTML(f *Function, phase string, dot *dotWriter) string {
- buf := new(bytes.Buffer)
- if dot != nil {
- dot.writeFuncSVG(buf, phase, f)
- }
- fmt.Fprint(buf, "")
- p := htmlFuncPrinter{w: buf}
- fprintFunc(p, f)
-
- // fprintFunc(&buf, f) // TODO: HTML, not text, for line breaks, etc.
- fmt.Fprint(buf, "")
- return buf.String()
-}
-
-type htmlFuncPrinter struct {
- w io.Writer
-}
-
-func (p htmlFuncPrinter) startBlock(b *BasicBlock, reachable bool) {
- var dead string
- if !reachable {
- dead = "dead-block"
- }
- fmt.Fprintf(p.w, "
", b, dead)
- fmt.Fprintf(p.w, "
%s:", blockHTML(b))
- if len(b.Preds) > 0 {
- io.WriteString(p.w, " ←") // left arrow
- for _, pred := range b.Preds {
- fmt.Fprintf(p.w, " %s", blockHTML(pred))
- }
- }
- if len(b.Instrs) > 0 {
- io.WriteString(p.w, ``)
- }
- io.WriteString(p.w, "
")
- if len(b.Instrs) > 0 { // start list of values
- io.WriteString(p.w, "
")
- io.WriteString(p.w, "
")
- }
-}
-
-func (p htmlFuncPrinter) endBlock(b *BasicBlock) {
- if len(b.Instrs) > 0 { // end list of values
- io.WriteString(p.w, "