Skip to content

Commit c8a4d2d

Browse files
committed
feat(exclusionfilter): limit exclusions to matching keys/values, if configured and in the issue
1 parent bc9372b commit c8a4d2d

1 file changed

Lines changed: 57 additions & 15 deletions

File tree

exclusion_filter.go

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ type ExcludeRule struct {
1919

2020
// compiledExcludeRule is a pre-compiled version of PathExcludeRule for efficient matching
2121
type compiledExcludeRule struct {
22-
pathRegex *regexp.Regexp
23-
keyRegexes []*regexp.Regexp
24-
valueRegexes []*regexp.Regexp
25-
ruleSet map[string]bool // Set of rule IDs to exclude
26-
excludeAll bool // True if "*" was specified in rules
27-
original ExcludeRule // Keep original for error messages
22+
pathRegex *regexp.Regexp
23+
keyRegexes []*regexp.Regexp
24+
valueRegexes []*regexp.Regexp
25+
ruleSet map[string]bool // Set of rule IDs to exclude
26+
excludeAll bool // True if "*" was specified in rules
27+
noAddendaExcludes bool // True if no keyRegexes or valueRegexes
28+
original ExcludeRule // Keep original for error messages
2829
}
2930

3031
// ExclusionFilter handles filtering of issues based on path and rule combinations
@@ -97,33 +98,74 @@ func NewExclusionFilter(rules []ExcludeRule) (*ExclusionFilter, error) {
9798
return nil, fmt.Errorf("exclude-rules[%d].values: %w", i, err)
9899
}
99100

101+
noAddendaExcludes := len(keyRegexes) == 0 && len(valueRegexes) == 0
102+
100103
ruleSet := make(map[string]bool)
101104
excludeAll := false
102105

103106
for _, ruleID := range rule.Rules {
104107
ruleID = strings.TrimSpace(ruleID)
105-
if ruleID == "*" {
108+
if ruleID == "*" && noAddendaExcludes {
106109
excludeAll = true
107110
} else if ruleID != "" {
108111
ruleSet[ruleID] = true
109112
}
110113
}
111114

112115
compiled = append(compiled, compiledExcludeRule{
113-
pathRegex: regex,
114-
keyRegexes: keyRegexes,
115-
valueRegexes: valueRegexes,
116-
ruleSet: ruleSet,
117-
excludeAll: excludeAll,
118-
original: rule,
116+
pathRegex: regex,
117+
keyRegexes: keyRegexes,
118+
valueRegexes: valueRegexes,
119+
ruleSet: ruleSet,
120+
excludeAll: excludeAll,
121+
noAddendaExcludes: noAddendaExcludes,
122+
original: rule,
119123
})
120124
}
121125

122126
return &ExclusionFilter{rules: compiled}, nil
123127
}
124128

129+
// ExcludesAddenda returns whether an issue containing addenda
130+
// should be excluded from the results, assuming all of the following:
131+
// - The issue's path matches the exclude rule.
132+
// - The issue's ruleID matches the exclude rule.
133+
//
134+
// In other words, this method will further limit the exlude rule's scope,
135+
// if the issue has addenda matching either keys or values
136+
// which were specified in the rule.
137+
func (r *compiledExcludeRule) ExcludesAddenda(addenda any) bool {
138+
if addenda == nil {
139+
return false
140+
}
141+
142+
if len(r.keyRegexes) > 0 {
143+
if keyer, ok := addenda.(Keyer); ok {
144+
key := keyer.Key()
145+
for _, regex := range r.keyRegexes {
146+
if RegexMatchWithCache(regex, key) {
147+
return true
148+
}
149+
}
150+
}
151+
}
152+
153+
if len(r.valueRegexes) > 0 {
154+
if valuer, ok := addenda.(Valuer); ok {
155+
value := valuer.Value()
156+
for _, regex := range r.valueRegexes {
157+
if RegexMatchWithCache(regex, value) {
158+
return true
159+
}
160+
}
161+
}
162+
}
163+
164+
return false
165+
}
166+
125167
// ShouldExclude returns true if the given issue should be excluded based on
126-
// its file path, rule ID, and addenda
168+
// its file path, rule ID, and addenda.
127169
func (f *ExclusionFilter) ShouldExclude(filePath, ruleID string, addenda any) bool {
128170
if f == nil || len(f.rules) == 0 {
129171
return false
@@ -138,7 +180,7 @@ func (f *ExclusionFilter) ShouldExclude(filePath, ruleID string, addenda any) bo
138180
return true
139181
}
140182
if rule.ruleSet[ruleID] {
141-
return true
183+
return rule.noAddendaExcludes || rule.ExcludesAddenda(addenda)
142184
}
143185
}
144186
}

0 commit comments

Comments
 (0)