Remove top down strict updatability checks
The enforce_strict_updatability_linting and apex_strict_updatability_lint
are some of the last top down mutators, and removing them will help
with incremental analysis. Both mutators are used to propagate a flag
to transitive java dependencies that causes them to add extra checks to
their lint rules to require that baselines not include any skipped
NewApi checks.
Instead of modifying dependencies to check the baselines, propagate the
baselines up to the modules that are requesting the checks, and perform
the checks on all transitive baselines there.
Bug: 367784740
Test: TestJavaLintStrictUpdatabilityLinting
Test: TestApexStrictUpdtabilityLint
Flag: EXEMPT refactor
Change-Id: Ief2e3b26d745da61f13e621d635a5879d9c56779
diff --git a/java/lint.go b/java/lint.go
index 5cd49a8..2cbefc3 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -100,32 +100,30 @@
buildModuleReportZip bool
}
-type LintDepSetsIntf interface {
- // Methods used to propagate strict_updatability_linting values.
- GetStrictUpdatabilityLinting() bool
- SetStrictUpdatabilityLinting(bool)
-}
-
type LintDepSets struct {
- HTML, Text, XML *android.DepSet[android.Path]
+ HTML, Text, XML, Baseline *android.DepSet[android.Path]
}
type LintDepSetsBuilder struct {
- HTML, Text, XML *android.DepSetBuilder[android.Path]
+ HTML, Text, XML, Baseline *android.DepSetBuilder[android.Path]
}
func NewLintDepSetBuilder() LintDepSetsBuilder {
return LintDepSetsBuilder{
- HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
- Text: android.NewDepSetBuilder[android.Path](android.POSTORDER),
- XML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ Text: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ XML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ Baseline: android.NewDepSetBuilder[android.Path](android.POSTORDER),
}
}
-func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder {
+func (l LintDepSetsBuilder) Direct(html, text, xml android.Path, baseline android.OptionalPath) LintDepSetsBuilder {
l.HTML.Direct(html)
l.Text.Direct(text)
l.XML.Direct(xml)
+ if baseline.Valid() {
+ l.Baseline.Direct(baseline.Path())
+ }
return l
}
@@ -139,14 +137,18 @@
if info.TransitiveXML != nil {
l.XML.Transitive(info.TransitiveXML)
}
+ if info.TransitiveBaseline != nil {
+ l.Baseline.Transitive(info.TransitiveBaseline)
+ }
return l
}
func (l LintDepSetsBuilder) Build() LintDepSets {
return LintDepSets{
- HTML: l.HTML.Build(),
- Text: l.Text.Build(),
- XML: l.XML.Build(),
+ HTML: l.HTML.Build(),
+ Text: l.Text.Build(),
+ XML: l.XML.Build(),
+ Baseline: l.Baseline.Build(),
}
}
@@ -194,16 +196,6 @@
},
}
-func (l *linter) GetStrictUpdatabilityLinting() bool {
- return BoolDefault(l.properties.Lint.Strict_updatability_linting, false)
-}
-
-func (l *linter) SetStrictUpdatabilityLinting(strictLinting bool) {
- l.properties.Lint.Strict_updatability_linting = &strictLinting
-}
-
-var _ LintDepSetsIntf = (*linter)(nil)
-
var LintProvider = blueprint.NewProvider[*LintInfo]()
type LintInfo struct {
@@ -212,9 +204,10 @@
XML android.Path
ReferenceBaseline android.Path
- TransitiveHTML *android.DepSet[android.Path]
- TransitiveText *android.DepSet[android.Path]
- TransitiveXML *android.DepSet[android.Path]
+ TransitiveHTML *android.DepSet[android.Path]
+ TransitiveText *android.DepSet[android.Path]
+ TransitiveXML *android.DepSet[android.Path]
+ TransitiveBaseline *android.DepSet[android.Path]
}
func (l *linter) enabled() bool {
@@ -250,7 +243,9 @@
return ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
}
-func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path) lintPaths {
+func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path,
+ baselines android.Paths) lintPaths {
+
projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml")
// Lint looks for a lint.xml file next to the project.xml file, give it one.
configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml")
@@ -313,12 +308,10 @@
cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
- if l.GetStrictUpdatabilityLinting() {
+ if Bool(l.properties.Lint.Strict_updatability_linting) && len(baselines) > 0 {
// Verify the module does not baseline issues that endanger safe updatability.
- if l.properties.Lint.Baseline_filename != nil {
- cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
- cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks)
- }
+ strictUpdatabilityChecksOutputFile := VerifyStrictUpdatabilityChecks(ctx, baselines)
+ cmd.Validation(strictUpdatabilityChecksOutputFile)
}
return lintPaths{
@@ -330,6 +323,22 @@
}
+func VerifyStrictUpdatabilityChecks(ctx android.ModuleContext, baselines android.Paths) android.Path {
+ rule := android.NewRuleBuilder(pctx, ctx)
+ baselineRspFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check_baselines.rsp")
+ outputFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check.stamp")
+ rule.Command().Text("rm -f").Output(outputFile)
+ rule.Command().
+ BuiltTool("lint_strict_updatability_checks").
+ FlagWithArg("--name ", ctx.ModuleName()).
+ FlagWithRspFileInputList("--baselines ", baselineRspFile, baselines).
+ FlagForEachArg("--disallowed_issues ", updatabilityChecks)
+ rule.Command().Text("touch").Output(outputFile)
+ rule.Build("lint_strict_updatability_checks", "lint strict updatability checks")
+
+ return outputFile
+}
+
// generateManifest adds a command to the rule to write a simple manifest that contains the
// minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest.
func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.WritablePath {
@@ -399,6 +408,26 @@
l.extraLintCheckJars = append(l.extraLintCheckJars, android.PathForSource(ctx,
"prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar"))
+ var baseline android.OptionalPath
+ if l.properties.Lint.Baseline_filename != nil {
+ baseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
+ }
+
+ html := android.PathForModuleOut(ctx, "lint", "lint-report.html")
+ text := android.PathForModuleOut(ctx, "lint", "lint-report.txt")
+ xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml")
+ referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml")
+
+ depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml, baseline)
+
+ ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
+ if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok {
+ depSetsBuilder.Transitive(info)
+ }
+ })
+
+ depSets := depSetsBuilder.Build()
+
rule := android.NewRuleBuilder(pctx, ctx).
Sbox(android.PathForModuleOut(ctx, "lint"),
android.PathForModuleOut(ctx, "lint.sbox.textproto")).
@@ -425,22 +454,9 @@
srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp")
rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList).Implicits(l.compile_data)
- lintPaths := l.writeLintProjectXML(ctx, rule, srcsList)
+ baselines := depSets.Baseline.ToList()
- html := android.PathForModuleOut(ctx, "lint", "lint-report.html")
- text := android.PathForModuleOut(ctx, "lint", "lint-report.txt")
- xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml")
- referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml")
-
- depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml)
-
- ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
- if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok {
- depSetsBuilder.Transitive(info)
- }
- })
-
- depSets := depSetsBuilder.Build()
+ lintPaths := l.writeLintProjectXML(ctx, rule, srcsList, baselines)
rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
@@ -495,8 +511,8 @@
cmd.FlagWithArg("--check ", checkOnly)
}
- if l.properties.Lint.Baseline_filename != nil {
- cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
+ if baseline.Valid() {
+ cmd.FlagWithInput("--baseline ", baseline.Path())
}
cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline)
@@ -526,13 +542,14 @@
XML: xml,
ReferenceBaseline: referenceBaseline,
- TransitiveHTML: depSets.HTML,
- TransitiveText: depSets.Text,
- TransitiveXML: depSets.XML,
+ TransitiveHTML: depSets.HTML,
+ TransitiveText: depSets.Text,
+ TransitiveXML: depSets.XML,
+ TransitiveBaseline: depSets.Baseline,
})
if l.buildModuleReportZip {
- l.reports = BuildModuleLintReportZips(ctx, depSets)
+ l.reports = BuildModuleLintReportZips(ctx, depSets, nil)
}
// Create a per-module phony target to run the lint check.
@@ -542,7 +559,7 @@
ctx.SetOutputFiles(android.Paths{xml}, ".lint")
}
-func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths {
+func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets, validations android.Paths) android.Paths {
htmlList := android.SortedUniquePaths(depSets.HTML.ToList())
textList := android.SortedUniquePaths(depSets.Text.ToList())
xmlList := android.SortedUniquePaths(depSets.XML.ToList())
@@ -552,13 +569,13 @@
}
htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
- lintZip(ctx, htmlList, htmlZip)
+ lintZip(ctx, htmlList, htmlZip, validations)
textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
- lintZip(ctx, textList, textZip)
+ lintZip(ctx, textList, textZip, validations)
xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
- lintZip(ctx, xmlList, xmlZip)
+ lintZip(ctx, xmlList, xmlZip, validations)
return android.Paths{htmlZip, textZip, xmlZip}
}
@@ -668,7 +685,7 @@
}
}
- lintZip(ctx, paths, outputPath)
+ lintZip(ctx, paths, outputPath, nil)
}
l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
@@ -697,17 +714,9 @@
func init() {
android.RegisterParallelSingletonType("lint",
func() android.Singleton { return &lintSingleton{} })
-
- registerLintBuildComponents(android.InitRegistrationContext)
}
-func registerLintBuildComponents(ctx android.RegistrationContext) {
- ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("enforce_strict_updatability_linting", enforceStrictUpdatabilityLintingMutator).Parallel()
- })
-}
-
-func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath) {
+func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath, validations android.Paths) {
paths = android.SortedUniquePaths(android.CopyOfPaths(paths))
sort.Slice(paths, func(i, j int) bool {
@@ -719,19 +728,8 @@
rule.Command().BuiltTool("soong_zip").
FlagWithOutput("-o ", outputPath).
FlagWithArg("-C ", android.PathForIntermediates(ctx).String()).
- FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths)
+ FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths).
+ Validations(validations)
rule.Build(outputPath.Base(), outputPath.Base())
}
-
-// Enforce the strict updatability linting to all applicable transitive dependencies.
-func enforceStrictUpdatabilityLintingMutator(ctx android.TopDownMutatorContext) {
- m := ctx.Module()
- if d, ok := m.(LintDepSetsIntf); ok && d.GetStrictUpdatabilityLinting() {
- ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
- if a, ok := d.(LintDepSetsIntf); ok {
- a.SetStrictUpdatabilityLinting(true)
- }
- })
- }
-}