| // Copyright 2021 The Fuchsia 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 core |
| |
| import ( |
| "fmt" |
| ) |
| |
| // allRules is evil global mutable state, but we're being super careful about |
| // how it is used. It can be mutated only through registration, all other uses |
| // are read only. We do not rely on the registry in tests. |
| var allRules = make(map[string]func(rootReporter *RootReporter) (LintRuleOverTokens, LintRuleOverEvents)) |
| |
| // HasRule tests whether a given rule is registered. |
| func HasRule(name string) bool { |
| _, ok := allRules[name] |
| return ok |
| } |
| |
| // AllRules returns the names of all the registered rules. |
| func AllRules() []string { |
| var names []string |
| for name := range allRules { |
| names = append(names, name) |
| } |
| return names |
| } |
| |
| // CombineRules combines rules over tokens and rules over events into a single |
| // rule over tokens. |
| // |
| // To accomplish this combination, dedicated one-to-many rules bridge between |
| // the returned rule and the provided rules. Additionally, the token stream is |
| // recognized and turned into an event stream so as to drive all rules over |
| // events. |
| func CombineRules(rulesOverTokens []LintRuleOverTokens, rulesOverEvents []LintRuleOverEvents) LintRuleOverTokens { |
| // combining all rules into a single rule over tokens |
| // |
| // - oneToManyOverTokens rule over |
| // - all rules over tokens |
| // - a recognizer bridging to a |
| // - oneToManyOverEvents rule over |
| // - all rules over events |
| return oneToManyOverTokens(append( |
| rulesOverTokens, |
| &recognizer{ |
| rule: oneToManyOverEvents( |
| rulesOverEvents), |
| })) |
| } |
| |
| // InstantiateRules instantiates all `enabledRules`. |
| func InstantiateRules(rootReporter *RootReporter, enabledRules []string) LintRuleOverTokens { |
| var ( |
| rulesOverTokens []LintRuleOverTokens |
| rulesOverEvents []LintRuleOverEvents |
| ) |
| if len(enabledRules) == 1 && enabledRules[0] == AllRulesName { |
| enabledRules = nil |
| for name := range allRules { |
| enabledRules = append(enabledRules, name) |
| } |
| } |
| for _, name := range enabledRules { |
| instantiator, ok := allRules[name] |
| if !ok { |
| panic(fmt.Sprintf("unknown rule '%s', should not happen", name)) |
| } |
| overTokens, overEvents := instantiator(rootReporter) |
| if overTokens != nil { |
| rulesOverTokens = append(rulesOverTokens, overTokens) |
| } |
| if overEvents != nil { |
| rulesOverEvents = append(rulesOverEvents, overEvents) |
| } |
| } |
| return CombineRules(rulesOverTokens, rulesOverEvents) |
| } |
| |
| // RegisterLintRuleOverTokens registers a lint rule over tokens. This meant to |
| // be called from an `init` block. |
| func RegisterLintRuleOverTokens(name string, instantiator func(Reporter) LintRuleOverTokens) { |
| checkRegisteredName(name) |
| allRules[name] = func(rootReporter *RootReporter) (LintRuleOverTokens, LintRuleOverEvents) { |
| return instantiator(rootReporter.ForRule(name)), nil |
| } |
| } |
| |
| // RegisterLintRuleOverEvents registers a lint rule over events. This meant to |
| // be called from an `init` block. |
| func RegisterLintRuleOverEvents(name string, instantiator func(Reporter) LintRuleOverEvents) { |
| checkRegisteredName(name) |
| allRules[name] = func(rootReporter *RootReporter) (LintRuleOverTokens, LintRuleOverEvents) { |
| return nil, instantiator(rootReporter.ForRule(name)) |
| } |
| } |
| |
| // generalName is the category name reserved for warnings not issued by specific |
| // rules, but rather 'general' warnings. |
| const generalName = "general" |
| |
| // AllRulesName is a reserved rule name used to indicate "all" rules. |
| const AllRulesName = "all" |
| |
| func checkRegisteredName(name string) { |
| if name == generalName || name == AllRulesName { |
| panic(fmt.Sprintf("rule name '%s' is reserved", generalName)) |
| } |
| if _, ok := allRules[name]; ok { |
| panic(fmt.Sprintf("rule name '%s' is being registered more than once", name)) |
| } |
| } |