Skip to content

Commit 029010b

Browse files
authored
Merge pull request #114 from JoelSpeed/registry-refactor
Refactor to make analyzers independent
2 parents 2627b31 + 8fbe44b commit 029010b

File tree

81 files changed

+2871
-1928
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+2871
-1928
lines changed

docs/linters.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ The `jsontags` linter checks the tag name against the regex `"^[a-z][a-z0-9]*(?:
113113

114114
```yaml
115115
lintersConfig:
116-
jsonTags:
116+
jsontags:
117117
jsonTagRegex: "^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$" # Provide a custom regex, which the json tag must match.
118118
```
119119

@@ -178,7 +178,7 @@ In this case, the `omitempty` policy can be set to `Ignore`, and the linter will
178178

179179
```yaml
180180
lintersConfig:
181-
optionalFields:
181+
optionalfields:
182182
pointers:
183183
preference: Always | WhenRequired # Whether to always require pointers, or only when required. Defaults to `Always`.
184184
policy: SuggestFix | Warn # The policy for pointers in optional fields. Defaults to `SuggestFix`.
@@ -216,7 +216,7 @@ The `optionalorrequired` linter also checks for the presence of optional or requ
216216

217217
```yaml
218218
lintersConfig:
219-
optionalOrRequired:
219+
optionalorrequired:
220220
preferredOptionalMarker: optional | kubebuilder:validation:Optional # The preferred optional marker to use, fixes will suggest to use this marker. Defaults to `optional`.
221221
preferredRequiredMarker: required | kubebuilder:validation:Required # The preferred required marker to use, fixes will suggest to use this marker. Defaults to `required`.
222222
```
@@ -236,7 +236,7 @@ and not having an `omitempty` value in their `json` tag.
236236

237237
```yaml
238238
lintersConfig:
239-
requiredFields:
239+
requiredfields:
240240
pointerPolicy: Warn | SuggestFix # The policy for pointers in required fields. Defaults to `SuggestFix`.
241241
```
242242

@@ -326,7 +326,7 @@ Because this linter has no way of determining which marker definition was intend
326326
It can configured to include a set of custom markers in the analysis by setting:
327327
```yaml
328328
lintersConfig:
329-
uniqueMarkers:
329+
uniquemarkers:
330330
customMarkers:
331331
- identifier: custom:SomeCustomMarker
332332
attributes:

docs/new-linter.md

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,70 +24,70 @@ Once you are within the `inspect.Preorder`, you can then implement the business
2424
The registry in the analysis package co-ordinates the initialization of all linters.
2525
Where linters have configuration, or are enabled/disabled by higher level configuration, the registry takes on making sure the linters are initialized correctly.
2626

27-
To enable the registry, each linter package must create an `Initializer` function that returns an `analysis.AnalyzerInitializer` interface (from `pkg/analysis`).
27+
To enable the registry, each linter package must create an `Initializer` function that returns an `initializer.AnalyzerInitializer` interface (from `pkg/analysis/initializer`).
2828

2929
It is expected that each linter package contain a file `initializer.go`, the content of this file should be as follows:
3030

3131
```go
32-
// Initializer returns the AnalyzerInitializer for this
33-
// Analyzer so that it can be added to the registry.
34-
func Initializer() initializer {
35-
return initializer{}
36-
}
37-
38-
// intializer implements the AnalyzerInitializer interface.
39-
type initializer struct{}
40-
41-
// Name returns the name of the Analyzer.
42-
func (initializer) Name() string {
43-
return name
44-
}
45-
46-
// Init returns the intialized Analyzer.
47-
func (initializer) Init(cfg config.LintersConfig) (*analysis.Analyzer, error) {
48-
return newAnalyzer(cfg.MyLinterConfig)
32+
func init() {
33+
// Register the linter with the registry when the package is imported.
34+
registry.DefaultRegistry().RegisterLinter(Initializer())
4935
}
5036

51-
// Default determines whether this Analyzer is on by default, or not.
52-
func (initializer) Default() bool {
53-
return true // or false
37+
// Initializer returns the AnalyzerInitializer for this
38+
// Analyzer so that it can be added to the registry.
39+
func Initializer() initializer.AnalyzerInitializer {
40+
return initializer.NewInitializer(
41+
name, // A constant containing the name of the linter. This should be lowercase.
42+
Analyzer, // An *analysis.Analyzer variable that is the linter.
43+
true, // Whether the linter is enabled by default.
44+
)
5445
}
5546
```
5647

57-
This pattern allows the linter to be registered with the KAL registry, and allows the linter to be initialized with configuration.
48+
This pattern allows the linter to be registered with the KAL registry, and allows the linter to be initialized.
5849

59-
Once you have created the `initializer.go` file, you will need to add the linter to the `pkg/analysis/registry.go` file.
50+
Once you have created the `initializer.go` file, you will need to import the linter package in the `pkg/analysis/registration/registration.go` file.
6051

61-
Add the initializer to the `NewRegistry` function, and it will then be included in the linter builds.
62-
63-
```go
64-
func NewRegistry() []*analysis.Analyzer {
65-
return []*analysis.Analyzer{
66-
// Add the new linter here
67-
mynewlinter.Initializer(),
68-
}
69-
}
70-
```
52+
Once imported, the analyzer will be included in the linter builds.
7153

7254
## Configuration
7355

74-
If the linter requires configuration, the configuration should be added to the `config` package.
56+
Where the linter requires configuration, a slightly different pattern is used in `initializer.go`.
57+
This time, use `NewConfigurableInitializer` instead of `NewInitializer` and pass in a function to validate the linter configuration.
58+
59+
```go
7560

76-
Add a new structure (or structures) to the `linters_config.go` file.
77-
Include a new field for the top level configuration to the `LintersConfig` struct, using the name of the linter, in camel case for the `json` tag.
61+
func init() {
62+
kalanalysis.DefaultRegistry().RegisterLinter(Initializer())
63+
}
7864

79-
Any options for the linter, should also be validated.
80-
Validation lives in the `validation` package.
65+
// Initializer returns the AnalyzerInitializer for this
66+
// Analyzer so that it can be added to the registry.
67+
func Initializer() initializer.AnalyzerInitializer {
68+
return initializer.NewConfigurableInitializer(
69+
name, // A constant containing the name of the linter. This should be lowercase.
70+
initAnalyzer, // A function that returns the initialized Analyzer.
71+
true, // Whether the linter is enabled by default.
72+
validateLintersConfig, // A function that validates the linter configuration.
73+
)
74+
}
8175

82-
Within the `ValidateLintersConfig` function, in the `linters_config.go` file, you will need to add
83-
a line as below, to include any configuration validation for the new linter.
84-
There are already examples of this in the file.
76+
// initAnalyzer returns the intialized Analyzer.
77+
func initAnalyzer(cfg *Config) (*analysis.Analyzer, error) {
78+
return newAnalyzer(cfg), nil
79+
}
8580

86-
```go
87-
fieldErrors = append(fieldErrors, validateMyNewLint(lc.MyNewLinter, fldPath.Child("myNewLinter"))...)
81+
// validateLintersConfig validates the linter configuration.
82+
func validateLintersConfig(cfg *Config, fldPath *field.Path) field.ErrorList {
83+
... // Validate the linter configuration.
84+
}
8885
```
8986

90-
The validations should use the `field.Error` pattern to provide consistent error messages.
87+
The configuration struct should be defined within the analyzer package alongside the code.
88+
89+
Validation should be implemented in the `validateLintersConfig` function to ensure that the configuration is valid.
90+
This validation function will be called before the `initAnalyzer` function is called.
9191

9292
## Helpers
9393

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/onsi/ginkgo/v2 v2.23.3
88
github.com/onsi/gomega v1.36.3
99
golang.org/x/tools v0.32.0
10+
gopkg.in/yaml.v3 v3.0.1
1011
k8s.io/apimachinery v0.32.3
1112
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
1213
)
@@ -26,5 +27,4 @@ require (
2627
golang.org/x/text v0.24.0 // indirect
2728
google.golang.org/protobuf v1.36.6 // indirect
2829
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
29-
gopkg.in/yaml.v3 v3.0.1 // indirect
3030
)

pkg/analysis/commentstart/initializer.go

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,20 @@ limitations under the License.
1616
package commentstart
1717

1818
import (
19-
"golang.org/x/tools/go/analysis"
20-
"sigs.k8s.io/kube-api-linter/pkg/config"
19+
"sigs.k8s.io/kube-api-linter/pkg/analysis/initializer"
20+
"sigs.k8s.io/kube-api-linter/pkg/analysis/registry"
2121
)
2222

23-
// Initializer returns the AnalyzerInitializer for this
24-
// Analyzer so that it can be added to the registry.
25-
func Initializer() initializer {
26-
return initializer{}
27-
}
28-
29-
// intializer implements the AnalyzerInitializer interface.
30-
type initializer struct{}
31-
32-
// Name returns the name of the Analyzer.
33-
func (initializer) Name() string {
34-
return name
23+
func init() {
24+
registry.DefaultRegistry().RegisterLinter(Initializer())
3525
}
3626

37-
// Init returns the intialized Analyzer.
38-
func (initializer) Init(cfg config.LintersConfig) (*analysis.Analyzer, error) {
39-
return Analyzer, nil
40-
}
41-
42-
// Default determines whether this Analyzer is on by default, or not.
43-
func (initializer) Default() bool {
44-
return true
27+
// Initializer returns the AnalyzerInitializer for this
28+
// Analyzer so that it can be added to the registry.
29+
func Initializer() initializer.AnalyzerInitializer {
30+
return initializer.NewInitializer(
31+
name,
32+
Analyzer,
33+
true,
34+
)
4535
}

0 commit comments

Comments
 (0)