Skip to content

Commit 3df1813

Browse files
authored
Add rule coverage (#126)
* Add rule coverage
1 parent 71556ad commit 3df1813

File tree

8 files changed

+50
-10
lines changed

8 files changed

+50
-10
lines changed

language/scala/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ go_library(
1111
"cache.go",
1212
"configure.go",
1313
"conflict_resolver_registry.go",
14+
"coverage.go",
1415
"cross_resolve.go",
1516
"deps_cleaner_registry.go",
1617
"existing_scala_rule.go",
@@ -79,6 +80,7 @@ gazelle_binary(
7980
go_test(
8081
name = "scala_test",
8182
srcs = [
83+
"coverage_test.go",
8284
"existing_scala_rule_test.go",
8385
"flags_test.go",
8486
"golden_test.go",

language/scala/coverage.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package scala
2+
3+
type packageRuleCoverage struct {
4+
// managed represents the total number of rules that are managed by
5+
// scala-gazelle (actual number of rules that we provided deps for)
6+
managed int
7+
// total represents the total number of rules in a package that we have a
8+
// RuleProvider for.
9+
total int
10+
}
11+
12+
func (sl *scalaLang) reportCoverage(printf func(format string, v ...any)) {
13+
if !sl.existingScalaRuleCoverageFlagValue {
14+
return
15+
}
16+
17+
var managed int
18+
var total int
19+
for _, pkg := range sl.packages {
20+
managed += pkg.ruleCoverage.managed
21+
total += pkg.ruleCoverage.total
22+
}
23+
24+
percent := float32(managed) / float32(total) * 100
25+
26+
printf("scala-gazelle coverage is %0.1f%% (%d/%d)", percent, managed, total)
27+
}

language/scala/coverage_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package scala

language/scala/flags.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const (
2323
existingScalaBinaryRuleFlagName = "existing_scala_binary_rule"
2424
existingScalaLibraryRuleFlagName = "existing_scala_library_rule"
2525
existingScalaTestRuleFlagName = "existing_scala_test_rule"
26+
existingScalaRuleCoverageFlagName = "existing_scala_rule_coverage"
2627
scalaGazelleCacheFileFlagName = "scala_gazelle_cache_file"
2728
scalaGazelleDebugProcessFileFlagName = "scala_gazelle_debug_process"
2829
scalaGazelleCacheKeyFlagName = "scala_gazelle_cache_key"
@@ -35,6 +36,7 @@ const (
3536
func (sl *scalaLang) RegisterFlags(flags *flag.FlagSet, cmd string, c *config.Config) {
3637
flags.BoolVar(&sl.debugProcessFlagValue, scalaGazelleDebugProcessFileFlagName, false, "if true, prints the process ID and waits for debugger to attach")
3738
flags.BoolVar(&sl.printCacheKey, scalaGazellePrintCacheKeyFlagName, true, "if a cache key is set, print the version for auditing purposes")
39+
flags.BoolVar(&sl.existingScalaRuleCoverageFlagValue, existingScalaRuleCoverageFlagName, true, "report coverage statistics")
3840
flags.StringVar(&sl.cacheFileFlagValue, scalaGazelleCacheFileFlagName, "", "optional path a cache file (.json or .pb)")
3941
flags.StringVar(&sl.cacheKeyFlagValue, scalaGazelleCacheKeyFlagName, "", "optional string that can be used to bust the cache file")
4042
flags.StringVar(&sl.cpuprofileFlagValue, cpuprofileFileFlagName, "", "optional path a cpuprofile file (.prof)")

language/scala/language.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ type scalaLang struct {
5050
existingScalaLibraryRulesFlagValue collections.StringSlice
5151
// existingScalaLibraryRulesFlagValue is the value of the
5252
// existing_scala_test_rule repeatable flag
53-
existingScalaTestRulesFlagValue collections.StringSlice
54-
cpuprofileFlagValue string
55-
memprofileFlagValue string
53+
existingScalaTestRulesFlagValue collections.StringSlice
54+
cpuprofileFlagValue string
55+
existingScalaRuleCoverageFlagValue bool
56+
memprofileFlagValue string
5657
// cache is the loaded cache, if configured
5758
cache scpb.Cache
5859
// ruleProviderRegistry is the rule registry implementation. This holds the

language/scala/lifecycle.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func (sl *scalaLang) onEnd() {
3737
}
3838
}
3939

40+
sl.reportCoverage(log.Printf)
4041
sl.stopCpuProfiling()
4142
sl.stopMemoryProfiling()
4243
}

language/scala/scala_package.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ type scalaPackage struct {
4545
// resolveFuncs is a list of resolve work that needs to be deferred until
4646
// all rules in a package have been processed.
4747
resolveWork []func()
48+
// used for tracking coverage
49+
ruleCoverage *packageRuleCoverage
4850
}
4951

5052
// newScalaPackage constructs a Package given a list of scala files.
@@ -64,6 +66,7 @@ func newScalaPackage(
6466
cfg: cfg,
6567
rules: make(map[string]*rule.Rule),
6668
resolveWork: make([]func(), 0),
69+
ruleCoverage: &packageRuleCoverage{},
6770
}
6871
s.gen = s.generateRules(true)
6972
// s.empty = s.generateRules(false)
@@ -127,31 +130,35 @@ func (s *scalaPackage) generateRules(enabled bool) []scalarule.RuleProvider {
127130
for _, r := range s.file.Rules {
128131
fqn := fullyQualifiedLoadName(s.file.Loads, r.Kind())
129132
existingRulesByFQN[fqn] = append(existingRulesByFQN[fqn], r)
133+
if _, ok := s.providerRegistry.LookupProvider(fqn); ok {
134+
s.ruleCoverage.total += 1
135+
}
130136
}
131137
}
132138

133139
configuredRules := s.cfg.ConfiguredRules()
134140

135-
for _, rc := range configuredRules {
141+
for _, ruleConfig := range configuredRules {
136142
// if enabled != rc.Enabled {
137-
if !rc.Enabled {
143+
if !ruleConfig.Enabled {
138144
// log.Printf("%s: skipping rule config %s (not enabled)", s.rel, rc.Name)
139145
continue
140146
}
141-
rule := s.provideRule(rc)
147+
rule := s.provideRule(ruleConfig)
142148
if rule != nil {
143149
rules = append(rules, rule)
144150
}
145-
existing := existingRulesByFQN[rc.Implementation]
151+
existing := existingRulesByFQN[ruleConfig.Implementation]
146152
if len(existing) > 0 {
147153
for _, r := range existing {
148-
rule := s.resolveRule(rc, r)
154+
rule := s.resolveRule(ruleConfig, r)
149155
if rule != nil {
156+
s.ruleCoverage.managed += 1
150157
rules = append(rules, rule)
151158
}
152159
}
153160
}
154-
delete(existingRulesByFQN, rc.Implementation)
161+
delete(existingRulesByFQN, ruleConfig.Implementation)
155162
}
156163

157164
return rules

pkg/scalaconfig/config.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,6 @@ func (c *Config) GetImplicitImports(lang, imp string) (deps []string) {
406406

407407
// ConfiguredRules returns an ordered list of configured rules
408408
func (c *Config) ConfiguredRules() []*scalarule.Config {
409-
410409
names := make([]string, 0)
411410
for name := range c.rules {
412411
names = append(names, name)

0 commit comments

Comments
 (0)