Skip to content

Commit f1800a3

Browse files
committed
Solve issue #551
`—ignore-file` is now accepted on all commands, including the language server,
1 parent 1db130a commit f1800a3

12 files changed

+245
-56
lines changed

cmd/build_results.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ func BuildResults(
2323
base string,
2424
remote bool,
2525
timeout time.Duration,
26-
httpClientConfig utils.HTTPClientConfig) (*model.RuleResultSet, *motor.RuleSetExecutionResult, error) {
27-
return BuildResultsWithDocCheckSkip(silent, hardMode, rulesetFlag, specBytes, customFunctions, base, remote, false, timeout, httpClientConfig)
26+
httpClientConfig utils.HTTPClientConfig,
27+
ignoredItems model.IgnoredItems) (*model.RuleResultSet, *motor.RuleSetExecutionResult, error) {
28+
return BuildResultsWithDocCheckSkip(silent, hardMode, rulesetFlag, specBytes, customFunctions, base, remote, false, timeout, httpClientConfig, ignoredItems)
2829
}
2930

3031
func BuildResultsWithDocCheckSkip(
@@ -37,7 +38,8 @@ func BuildResultsWithDocCheckSkip(
3738
remote bool,
3839
skipCheck bool,
3940
timeout time.Duration,
40-
httpClientConfig utils.HTTPClientConfig) (*model.RuleResultSet, *motor.RuleSetExecutionResult, error) {
41+
httpClientConfig utils.HTTPClientConfig,
42+
ignoredItems model.IgnoredItems) (*model.RuleResultSet, *motor.RuleSetExecutionResult, error) {
4143

4244
// read spec and parse
4345
defaultRuleSets := rulesets.BuildDefaultRuleSets()
@@ -116,5 +118,6 @@ func BuildResultsWithDocCheckSkip(
116118

117119
resultSet := model.NewRuleResultSet(ruleset.Results)
118120
resultSet.SortResultsByLineNumber()
121+
resultSet.Results = utils.FilterIgnoredResultsPtr(resultSet.Results, ignoredItems)
119122
return resultSet, ruleset, nil
120123
}

cmd/build_results_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
package cmd
22

33
import (
4+
"github.com/daveshanley/vacuum/model"
45
"github.com/daveshanley/vacuum/utils"
56
"github.com/stretchr/testify/assert"
67
"testing"
78
)
89

910
func TestBuildResults(t *testing.T) {
10-
_, _, err := BuildResults(false, false, "nuggets", nil, nil, "", true, 5, utils.HTTPClientConfig{})
11+
_, _, err := BuildResults(false, false, "nuggets", nil, nil, "", true, 5, utils.HTTPClientConfig{}, model.IgnoredItems{})
1112
assert.Error(t, err)
1213
}
1314

1415
func TestBuildResults_SkipCheck(t *testing.T) {
15-
_, _, err := BuildResultsWithDocCheckSkip(false, false, "nuggets", nil, nil, "", true, true, 5, utils.HTTPClientConfig{})
16+
_, _, err := BuildResultsWithDocCheckSkip(false, false, "nuggets", nil, nil, "", true, true, 5, utils.HTTPClientConfig{}, model.IgnoredItems{})
1617
assert.Error(t, err)
1718
}

cmd/dashboard.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package cmd
55

66
import (
77
"errors"
8+
"fmt"
89
"github.com/daveshanley/vacuum/cui"
910
"github.com/daveshanley/vacuum/model"
1011
"github.com/daveshanley/vacuum/motor"
@@ -16,12 +17,13 @@ import (
1617
"github.com/spf13/cobra"
1718
"gopkg.in/yaml.v3"
1819
"net/url"
20+
"os"
1921
"time"
2022
)
2123

2224
func GetDashboardCommand() *cobra.Command {
2325

24-
return &cobra.Command{
26+
cmd := &cobra.Command{
2527
Use: "dashboard",
2628
Short: "Show vacuum dashboard for linting report",
2729
Long: "Interactive console dashboard to explore linting report in detail",
@@ -48,6 +50,7 @@ func GetDashboardCommand() *cobra.Command {
4850
silent, _ := cmd.Flags().GetBool("silent")
4951
extensionRefsFlag, _ := cmd.Flags().GetBool("ext-refs")
5052
remoteFlag, _ := cmd.Flags().GetBool("remote")
53+
ignoreFile, _ := cmd.Flags().GetString("ignore-file")
5154

5255
var err error
5356
vacuumReport, specBytes, _ := vacuum_report.BuildVacuumReportFromFile(args[0])
@@ -61,6 +64,18 @@ func GetDashboardCommand() *cobra.Command {
6164
var specIndex *index.SpecIndex
6265
var specInfo *datamodel.SpecInfo
6366

67+
ignoredItems := model.IgnoredItems{}
68+
if ignoreFile != "" {
69+
raw, ferr := os.ReadFile(ignoreFile)
70+
if ferr != nil {
71+
return fmt.Errorf("failed to read ignore file: %w", ferr)
72+
}
73+
ferr = yaml.Unmarshal(raw, &ignoredItems)
74+
if ferr != nil {
75+
return fmt.Errorf("failed to parse ignore file: %w", ferr)
76+
}
77+
}
78+
6479
// if we have a pre-compiled report, jump straight to the end and collect $500
6580
if vacuumReport == nil {
6681

@@ -80,7 +95,7 @@ func GetDashboardCommand() *cobra.Command {
8095
KeyFile: keyFile,
8196
CAFile: caFile,
8297
Insecure: insecure,
83-
})
98+
}, ignoredItems)
8499
if err != nil {
85100
pterm.Error.Printf("Failed to render dashboard: %v\n\n", err)
86101
return err
@@ -92,6 +107,7 @@ func GetDashboardCommand() *cobra.Command {
92107
} else {
93108

94109
resultSet = model.NewRuleResultSetPointer(vacuumReport.ResultSet.Results)
110+
resultSet.Results = utils.FilterIgnoredResultsPtr(resultSet.Results, ignoredItems)
95111

96112
// TODO: refactor dashboard to hold state and rendering as separate entities.
97113
// dashboard will be slower because it needs an index
@@ -138,4 +154,6 @@ func GetDashboardCommand() *cobra.Command {
138154
return dash.Render()
139155
},
140156
}
157+
cmd.Flags().String("ignore-file", "", "Path to ignore file")
158+
return cmd
141159
}

cmd/html_report.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ package cmd
66
import (
77
"errors"
88
html_report "github.com/daveshanley/vacuum/html-report"
9+
"fmt"
910
"github.com/daveshanley/vacuum/model"
1011
"github.com/daveshanley/vacuum/model/reports"
1112
"github.com/daveshanley/vacuum/motor"
13+
"gopkg.in/yaml.v3"
1214
"github.com/daveshanley/vacuum/statistics"
1315
"github.com/daveshanley/vacuum/utils"
1416
vacuum_report "github.com/daveshanley/vacuum/vacuum-report"
@@ -49,6 +51,7 @@ func GetHTMLReportCommand() *cobra.Command {
4951
hardModeFlag, _ := cmd.Flags().GetBool("hard-mode")
5052
silent, _ := cmd.Flags().GetBool("silent")
5153
remoteFlag, _ := cmd.Flags().GetBool("remote")
54+
ignoreFile, _ := cmd.Flags().GetString("ignore-file")
5255

5356
// disable color and styling, for CI/CD use.
5457
// https://github.com/daveshanley/vacuum/issues/234
@@ -90,6 +93,18 @@ func GetHTMLReportCommand() *cobra.Command {
9093
var specInfo *datamodel.SpecInfo
9194
var stats *reports.ReportStatistics
9295

96+
ignoredItems := model.IgnoredItems{}
97+
if ignoreFile != "" {
98+
raw, ferr := os.ReadFile(ignoreFile)
99+
if ferr != nil {
100+
return fmt.Errorf("failed to read ignore file: %w", ferr)
101+
}
102+
ferr = yaml.Unmarshal(raw, &ignoredItems)
103+
if ferr != nil {
104+
return fmt.Errorf("failed to parse ignore file: %w", ferr)
105+
}
106+
}
107+
93108
// if we have a pre-compiled report, jump straight to the end and collect $500
94109
if vacuumReport == nil {
95110

@@ -110,7 +125,7 @@ func GetHTMLReportCommand() *cobra.Command {
110125
KeyFile: keyFile,
111126
CAFile: caFile,
112127
Insecure: insecure,
113-
})
128+
}, ignoredItems)
114129
if err != nil {
115130
pterm.Error.Printf("Failed to generate report: %v\n\n", err)
116131
return err
@@ -124,6 +139,8 @@ func GetHTMLReportCommand() *cobra.Command {
124139
} else {
125140

126141
resultSet = model.NewRuleResultSetPointer(vacuumReport.ResultSet.Results)
142+
// Apply ignore filter to pre-compiled report results
143+
resultSet.Results = utils.FilterIgnoredResultsPtr(resultSet.Results, ignoredItems)
127144
specInfo = vacuumReport.SpecInfo
128145
stats = vacuumReport.Statistics
129146
specInfo.Generated = vacuumReport.Generated
@@ -156,6 +173,7 @@ func GetHTMLReportCommand() *cobra.Command {
156173
}
157174
cmd.Flags().BoolP("disableTimestamp", "d", false, "Disable timestamp in report")
158175
cmd.Flags().BoolP("no-style", "q", false, "Disable styling and color output, just plain text (useful for CI/CD)")
176+
cmd.Flags().String("ignore-file", "", "Path to ignore file")
159177

160178
return cmd
161179
}

cmd/language_server.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
package cmd
66

77
import (
8+
"fmt"
89
languageserver "github.com/daveshanley/vacuum/language-server"
10+
"github.com/daveshanley/vacuum/model"
911
"github.com/daveshanley/vacuum/rulesets"
1012
"github.com/daveshanley/vacuum/utils"
1113
"github.com/pterm/pterm"
1214
"github.com/spf13/cobra"
15+
"gopkg.in/yaml.v3"
1316
"io"
1417
"log/slog"
1518
"net/http"
19+
"os"
1620
)
1721

1822
func GetLanguageServerCommand() *cobra.Command {
@@ -40,8 +44,9 @@ IDE and start linting your OpenAPI documents in real-time.`,
4044
timeoutFlag, _ := cmd.Flags().GetInt("timeout")
4145
hardModeFlag, _ := cmd.Flags().GetBool("hard-mode")
4246
ignoreArrayCircleRef, _ := cmd.Flags().GetBool("ignore-array-circle-ref")
43-
ignorePolymorphCircleRef, _ := cmd.Flags().GetBool("ignore-array-circle-ref")
47+
ignorePolymorphCircleRef, _ := cmd.Flags().GetBool("ignore-polymorph-circle-ref")
4448
extensionRefsFlag, _ := cmd.Flags().GetBool("ext-refs")
49+
ignoreFile, _ := cmd.Flags().GetString("ignore-file")
4550

4651
defaultRuleSets := rulesets.BuildDefaultRuleSetsWithLogger(logger)
4752
selectedRS := defaultRuleSets.GenerateOpenAPIRecommendedRuleSet()
@@ -91,6 +96,18 @@ IDE and start linting your OpenAPI documents in real-time.`,
9196
}
9297
}
9398

99+
ignoredItems := model.IgnoredItems{}
100+
if ignoreFile != "" {
101+
raw, ferr := os.ReadFile(ignoreFile)
102+
if ferr != nil {
103+
return fmt.Errorf("failed to read ignore file: %w", ferr)
104+
}
105+
ferr = yaml.Unmarshal(raw, &ignoredItems)
106+
if ferr != nil {
107+
return fmt.Errorf("failed to parse ignore file: %w", ferr)
108+
}
109+
}
110+
94111
lfr := utils.LintFileRequest{
95112
BaseFlag: baseFlag,
96113
Remote: remoteFlag,
@@ -103,12 +120,14 @@ IDE and start linting your OpenAPI documents in real-time.`,
103120
IgnorePolymorphCircleRef: ignorePolymorphCircleRef,
104121
Logger: logger,
105122
ExtensionRefs: extensionRefsFlag,
123+
IgnoredResults: ignoredItems,
106124
}
107125

108126
return languageserver.NewServer(Version, &lfr).Run()
109127
},
110128
}
111129
cmd.Flags().Bool("ignore-array-circle-ref", false, "Ignore circular array references")
112130
cmd.Flags().Bool("ignore-polymorph-circle-ref", false, "Ignore circular polymorphic references")
131+
cmd.Flags().String("ignore-file", "", "Path to ignore file")
113132
return cmd
114133
}

cmd/lint.go

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ func lintFile(req utils.LintFileRequest) (*reports.ReportStatistics, int64, int,
448448
HTTPClientConfig: req.HTTPClientConfig,
449449
})
450450

451-
result.Results = filterIgnoredResults(result.Results, req.IgnoredResults)
451+
result.Results = utils.FilterIgnoredResults(result.Results, req.IgnoredResults)
452452

453453
if len(result.Errors) > 0 {
454454
for _, err := range result.Errors {
@@ -567,50 +567,6 @@ func lintFile(req utils.LintFileRequest) (*reports.ReportStatistics, int64, int,
567567
return stats, result.FileSize, result.FilesProcessed, CheckFailureSeverity(req.FailSeverityFlag, errs, warnings, informs)
568568
}
569569

570-
// filterIgnoredResultsPtr filters the given results slice, taking out any (RuleID, Path) combos that were listed in the
571-
// ignore file
572-
func filterIgnoredResultsPtr(results []*model.RuleFunctionResult, ignored model.IgnoredItems) []*model.RuleFunctionResult {
573-
var filteredResults []*model.RuleFunctionResult
574-
575-
for _, r := range results {
576-
577-
var found bool
578-
for _, i := range ignored[r.Rule.Id] {
579-
if len(r.Paths) > 0 {
580-
for _, p := range r.Paths {
581-
if p == i {
582-
found = true
583-
break
584-
}
585-
}
586-
}
587-
if r.Path == i {
588-
found = true
589-
break
590-
}
591-
592-
}
593-
if !found {
594-
filteredResults = append(filteredResults, r)
595-
}
596-
}
597-
598-
return filteredResults
599-
}
600-
601-
// filterIgnoredResults does the filtering of ignored results on non-pointer result elements
602-
func filterIgnoredResults(results []model.RuleFunctionResult, ignored model.IgnoredItems) []model.RuleFunctionResult {
603-
resultsPtrs := make([]*model.RuleFunctionResult, 0, len(results))
604-
for _, r := range results {
605-
r := r // prevent loop memory aliasing
606-
resultsPtrs = append(resultsPtrs, &r)
607-
}
608-
resultsFiltered := make([]model.RuleFunctionResult, 0, len(results))
609-
for _, r := range filterIgnoredResultsPtr(resultsPtrs, ignored) {
610-
resultsFiltered = append(resultsFiltered, *r)
611-
}
612-
return resultsFiltered
613-
}
614570

615571
func processResults(results []*model.RuleFunctionResult,
616572
specData []string,

cmd/lint_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"fmt"
66
"github.com/daveshanley/vacuum/model"
7+
"github.com/daveshanley/vacuum/utils"
78
"github.com/pterm/pterm"
89
"github.com/stretchr/testify/assert"
910
"io"
@@ -528,7 +529,7 @@ func TestFilterIgnoredResults(t *testing.T) {
528529
"YYY": []string{"a/b"},
529530
}
530531

531-
results = filterIgnoredResults(results, igItems)
532+
results = utils.FilterIgnoredResults(results, igItems)
532533

533534
expected := []model.RuleFunctionResult{
534535
{Path: "a/b", Rule: &model.Rule{Id: "XXX"}},

cmd/spectral_report.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/daveshanley/vacuum/motor"
1313
"github.com/daveshanley/vacuum/rulesets"
1414
"github.com/daveshanley/vacuum/utils"
15+
"gopkg.in/yaml.v3"
1516
"github.com/pterm/pterm"
1617
"github.com/spf13/cobra"
1718
"net/http"
@@ -51,6 +52,7 @@ func GetSpectralReportCommand() *cobra.Command {
5152
hardModeFlag, _ := cmd.Flags().GetBool("hard-mode")
5253
extensionRefsFlag, _ := cmd.Flags().GetBool("ext-refs")
5354
remoteFlag, _ := cmd.Flags().GetBool("remote")
55+
ignoreFile, _ := cmd.Flags().GetString("ignore-file")
5456

5557
// disable color and styling, for CI/CD use.
5658
// https://github.com/daveshanley/vacuum/issues/234
@@ -110,6 +112,18 @@ func GetSpectralReportCommand() *cobra.Command {
110112
return fileError
111113
}
112114

115+
ignoredItems := model.IgnoredItems{}
116+
if ignoreFile != "" {
117+
raw, ferr := os.ReadFile(ignoreFile)
118+
if ferr != nil {
119+
return fmt.Errorf("failed to read ignore file: %w", ferr)
120+
}
121+
ferr = yaml.Unmarshal(raw, &ignoredItems)
122+
if ferr != nil {
123+
return fmt.Errorf("failed to parse ignore file: %w", ferr)
124+
}
125+
}
126+
113127
rulesetFlag, _ := cmd.Flags().GetString("ruleset")
114128

115129
// read spec and parse to dashboard.
@@ -194,6 +208,8 @@ func GetSpectralReportCommand() *cobra.Command {
194208
resultSet := model.NewRuleResultSet(ruleset.Results)
195209
resultSet.SortResultsByLineNumber()
196210

211+
resultSet.Results = utils.FilterIgnoredResultsPtr(resultSet.Results, ignoredItems)
212+
197213
duration := time.Since(start)
198214

199215
var source string
@@ -246,6 +262,7 @@ func GetSpectralReportCommand() *cobra.Command {
246262
cmd.Flags().BoolP("stdout", "o", false, "Use stdout as output, instead of a file")
247263
cmd.Flags().BoolP("no-pretty", "n", false, "Render JSON with no formatting")
248264
cmd.Flags().BoolP("no-style", "q", false, "Disable styling and color output, just plain text (useful for CI/CD)")
265+
cmd.Flags().String("ignore-file", "", "Path to ignore file")
249266
return cmd
250267

251268
}

cmd/vacuum_report.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ func GetVacuumReportCommand() *cobra.Command {
216216
resultSet := model.NewRuleResultSet(ruleset.Results)
217217
resultSet.SortResultsByLineNumber()
218218

219-
resultSet.Results = filterIgnoredResultsPtr(resultSet.Results, ignoredItems)
219+
resultSet.Results = utils.FilterIgnoredResultsPtr(resultSet.Results, ignoredItems)
220220

221221
duration := time.Since(start)
222222

0 commit comments

Comments
 (0)