diff --git a/src/linter/utils.go b/src/linter/utils.go index f673fdc8d..bd56092b1 100644 --- a/src/linter/utils.go +++ b/src/linter/utils.go @@ -68,15 +68,15 @@ func mergeTypeMaps(left types.Map, right types.Map) types.Map { // The types are inferred as follows: // 1. If there is a @return annotation, then its value becomes the return type; // -// 2. If there is a type hint, then it is added to the types from the @return. -// If the @return is empty, then the type matches the type hint itself; +// 2. If there is a type hint, then it is added to the types from the @return. +// If the @return is empty, then the type matches the type hint itself; // -// 3. If the resulting type is mixed[], then if the actual type is a specific -// array type, then we use it, otherwise we combine this type with the -// resulting mixed[] type. +// 3. If the resulting type is mixed[], then if the actual type is a specific +// array type, then we use it, otherwise we combine this type with the +// resulting mixed[] type. // -// 4. If there is no @return annotation and type hint, then the return type is equal to -// the union of the types that are returned from the function by return. +// 4. If there is no @return annotation and type hint, then the return type is equal to +// the union of the types that are returned from the function by return. func functionReturnType(phpdocReturnType types.Map, hintReturnType types.Map, actualReturnTypes types.Map) types.Map { var returnTypes types.Map if !phpdocReturnType.Empty() || !hintReturnType.Empty() { @@ -494,10 +494,21 @@ func cloneRulesForFile(filename string, ruleSet *rules.ScopedSet) *rules.ScopedS for kind, ruleByKind := range &ruleSet.RulesByKind { res := make([]rules.Rule, 0, len(ruleByKind)) for _, rule := range ruleByKind { - if !strings.Contains(filename, rule.Path) || isFilePathExcluded(filename, rule) { + if isFilePathExcluded(filename, rule) { continue } - res = append(res, rule) + + if rule.Paths == nil { + res = append(res, rule) + continue + } + + for _, path := range rule.Paths { + if strings.Contains(filename, path) { + res = append(res, rule) + break + } + } } clone.Set(ir.NodeKind(kind), res) } diff --git a/src/rules/parser.go b/src/rules/parser.go index 0e9e9be64..ab7e0b827 100644 --- a/src/rules/parser.go +++ b/src/rules/parser.go @@ -141,7 +141,7 @@ func (p *parser) parseRuleInfo(st ir.Node, labelStmt ir.Node, proto *Rule) (Rule rule.Level = proto.Level rule.Message = proto.Message rule.Location = proto.Location - rule.Path = proto.Path + rule.Paths = proto.Paths rule.PathExcludes = proto.PathExcludes rule.Filters = make([]map[string]Filter, len(proto.Filters)) @@ -232,10 +232,12 @@ func (p *parser) parseRuleInfo(st ir.Node, labelStmt ir.Node, proto *Rule) (Rule if len(part.Params) != 1 { return rule, p.errorf(st, "@path expects exactly 1 param, got %d", len(part.Params)) } - if rule.Path != "" { - return rule, p.errorf(st, "duplicate @path constraint") + + if rule.Paths == nil { + rule.Paths = make([]string, 0) } - rule.Path = part.Params[0] + + rule.Paths = append(rule.Paths, part.Params...) case "path-exclude": if len(part.Params) != 1 { return rule, p.errorf(st, "@exclude expects exactly 1 param, got %d", len(part.Params)) diff --git a/src/rules/rules.go b/src/rules/rules.go index 5480585bc..8bed8f9ae 100644 --- a/src/rules/rules.go +++ b/src/rules/rules.go @@ -98,7 +98,7 @@ type Rule struct { // Path is a filter-like rule switcher. // A rule is only applied to a file that contains a Path as a substring in its name. - Path string + Paths []string // PathExcludes is a filter-like rule switcher. // A rule is not applied to a file that contains a PathExcludes as a substring in its name. diff --git a/src/rules/util.go b/src/rules/util.go index af84c003a..4251e4d0f 100644 --- a/src/rules/util.go +++ b/src/rules/util.go @@ -20,8 +20,8 @@ func formatRule(r *Rule) string { buf.WriteString(" * @maybe " + r.Message + "\n") } - if r.Path != "" { - buf.WriteString(" * @path " + r.Path + "\n") + for _, path := range r.Paths { + buf.WriteString(" * @path " + path + "\n") } if r.PathExcludes != nil { diff --git a/src/tests/rules/rules_error_test.go b/src/tests/rules/rules_error_test.go index a2c507c2b..151d7975e 100644 --- a/src/tests/rules/rules_error_test.go +++ b/src/tests/rules/rules_error_test.go @@ -132,19 +132,6 @@ $_ = foo(); `, expect: ":7: @path expects exactly 1 param, got 2", }, - { - name: `DuplicatedPath`, - rule: `:8: duplicate @path constraint", - }, { name: `PathExpectsExactlyTwoParam`, rule: `