Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87427354 authored by Colin Cross's avatar Colin Cross
Browse files

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
parent b34ca77d
Loading
Loading
Loading
Loading
+1 −23
Original line number Original line Diff line number Diff line
@@ -68,8 +68,6 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
	ctx.Transition("apex", &apexTransitionMutator{})
	ctx.Transition("apex", &apexTransitionMutator{})
	ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
	ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
	ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel()
	ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel()
	// Register after apex_info mutator so that it can use ApexVariationName
	ctx.TopDown("apex_strict_updatability_lint", apexStrictUpdatibilityLintMutator).Parallel()
}
}


type apexBundleProperties struct {
type apexBundleProperties struct {
@@ -1115,26 +1113,6 @@ func apexInfoMutator(mctx android.TopDownMutatorContext) {
	enforceAppUpdatability(mctx)
	enforceAppUpdatability(mctx)
}
}


// apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module
// This check is enforced for updatable modules
func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) {
	if !mctx.Module().Enabled(mctx) {
		return
	}
	if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting(mctx) {
		apex.WalkPayloadDeps(mctx, func(mctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
			if externalDep {
				return false
			}
			if lintable, ok := to.(java.LintDepSetsIntf); ok {
				lintable.SetStrictUpdatabilityLinting(true)
			}
			// visit transitive deps
			return true
		})
	}
}

// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
func enforceAppUpdatability(mctx android.TopDownMutatorContext) {
func enforceAppUpdatability(mctx android.TopDownMutatorContext) {
	if !mctx.Module().Enabled(mctx) {
	if !mctx.Module().Enabled(mctx) {
@@ -1197,7 +1175,7 @@ var (
	}
	}
)
)


func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.TopDownMutatorContext) bool {
func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.ModuleContext) bool {
	// The allowlist contains the base apex name, so use that instead of the ApexVariationName
	// The allowlist contains the base apex name, so use that instead of the ApexVariationName
	return a.Updatable() && !android.InList(mctx.ModuleName(), skipStrictUpdatabilityLintAllowlist)
	return a.Updatable() && !android.InList(mctx.ModuleName(), skipStrictUpdatabilityLintAllowlist)
}
}
+70 −44
Original line number Original line Diff line number Diff line
@@ -9697,39 +9697,45 @@ func TestApexStrictUpdtabilityLint(t *testing.T) {
		apexUpdatable                   bool
		apexUpdatable                   bool
		javaStrictUpdtabilityLint       bool
		javaStrictUpdtabilityLint       bool
		lintFileExists                  bool
		lintFileExists                  bool
		disallowedFlagExpected    bool
		disallowedFlagExpectedOnApex    bool
		disallowedFlagExpectedOnJavalib bool
	}{
	}{
		{
		{
			testCaseName:                    "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
			testCaseName:                    "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
			apexUpdatable:                   true,
			apexUpdatable:                   true,
			javaStrictUpdtabilityLint:       true,
			javaStrictUpdtabilityLint:       true,
			lintFileExists:                  false,
			lintFileExists:                  false,
			disallowedFlagExpected:    false,
			disallowedFlagExpectedOnApex:    false,
			disallowedFlagExpectedOnJavalib: false,
		},
		},
		{
		{
			testCaseName:                    "non-updatable apex respects strict_updatability of javalib",
			testCaseName:                    "non-updatable apex respects strict_updatability of javalib",
			apexUpdatable:                   false,
			apexUpdatable:                   false,
			javaStrictUpdtabilityLint:       false,
			javaStrictUpdtabilityLint:       false,
			lintFileExists:                  true,
			lintFileExists:                  true,
			disallowedFlagExpected:    false,
			disallowedFlagExpectedOnApex:    false,
			disallowedFlagExpectedOnJavalib: false,
		},
		},
		{
		{
			testCaseName:                    "non-updatable apex respects strict updatability of javalib",
			testCaseName:                    "non-updatable apex respects strict updatability of javalib",
			apexUpdatable:                   false,
			apexUpdatable:                   false,
			javaStrictUpdtabilityLint:       true,
			javaStrictUpdtabilityLint:       true,
			lintFileExists:                  true,
			lintFileExists:                  true,
			disallowedFlagExpected:    true,
			disallowedFlagExpectedOnApex:    false,
			disallowedFlagExpectedOnJavalib: true,
		},
		},
		{
		{
			testCaseName:              "updatable apex sets strict updatability of javalib to true",
			testCaseName:                    "updatable apex checks strict updatability of javalib",
			apexUpdatable:                   true,
			apexUpdatable:                   true,
			javaStrictUpdtabilityLint: false, // will be set to true by mutator
			javaStrictUpdtabilityLint:       false,
			lintFileExists:                  true,
			lintFileExists:                  true,
			disallowedFlagExpected:    true,
			disallowedFlagExpectedOnApex:    true,
			disallowedFlagExpectedOnJavalib: false,
		},
		},
	}
	}


	for _, testCase := range testCases {
	for _, testCase := range testCases {
		t.Run(testCase.testCaseName, func(t *testing.T) {
			fixtures := []android.FixturePreparer{}
			fixtures := []android.FixturePreparer{}
			baselineProperty := ""
			baselineProperty := ""
			if testCase.lintFileExists {
			if testCase.lintFileExists {
@@ -9739,13 +9745,32 @@ func TestApexStrictUpdtabilityLint(t *testing.T) {
			bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty)
			bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty)


			result := testApex(t, bp, fixtures...)
			result := testApex(t, bp, fixtures...)
		myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
		sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
		disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi")


		if disallowedFlagActual != testCase.disallowedFlagExpected {
			checkModule := func(m android.TestingBuildParams, name string, expectStrictUpdatability bool) {
			t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command)
				if expectStrictUpdatability {
					if m.Rule == nil {
						t.Errorf("expected strict updatability check rule on %s", name)
					} else {
						android.AssertStringDoesContain(t, fmt.Sprintf("strict updatability check rule for %s", name),
							m.RuleParams.Command, "--disallowed_issues NewApi")
						android.AssertStringListContains(t, fmt.Sprintf("strict updatability check baselines for %s", name),
							m.Inputs.Strings(), "lint-baseline.xml")
					}
					}
				} else {
					if m.Rule != nil {
						t.Errorf("expected no strict updatability check rule on %s", name)
					}
				}
			}

			myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
			apex := result.ModuleForTests("myapex", "android_common_myapex")
			apexStrictUpdatabilityCheck := apex.MaybeOutput("lint_strict_updatability_check.stamp")
			javalibStrictUpdatabilityCheck := myjavalib.MaybeOutput("lint_strict_updatability_check.stamp")

			checkModule(apexStrictUpdatabilityCheck, "myapex", testCase.disallowedFlagExpectedOnApex)
			checkModule(javalibStrictUpdatabilityCheck, "myjavalib", testCase.disallowedFlagExpectedOnJavalib)
		})
	}
	}
}
}


@@ -9787,11 +9812,12 @@ func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) {
	}
	}


	result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture())
	result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture())
	myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
	apex := result.ModuleForTests("myapex", "android_common_myapex")
	sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
	apexStrictUpdatabilityCheck := apex.Output("lint_strict_updatability_check.stamp")
	if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") {
	android.AssertStringDoesContain(t, "strict updatability check rule for myapex",
		t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command)
		apexStrictUpdatabilityCheck.RuleParams.Command, "--disallowed_issues NewApi")
	}
	android.AssertStringListContains(t, "strict updatability check baselines for myapex",
		apexStrictUpdatabilityCheck.Inputs.Strings(), "lint-baseline.xml")
}
}


func TestApexLintBcpFragmentSdkLibDeps(t *testing.T) {
func TestApexLintBcpFragmentSdkLibDeps(t *testing.T) {
+12 −1
Original line number Original line Diff line number Diff line
@@ -1164,7 +1164,18 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) {
		}
		}
	}
	}


	a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
	depSets := depSetsBuilder.Build()
	var validations android.Paths

	if a.checkStrictUpdatabilityLinting(ctx) {
		baselines := depSets.Baseline.ToList()
		if len(baselines) > 0 {
			outputFile := java.VerifyStrictUpdatabilityChecks(ctx, baselines)
			validations = append(validations, outputFile)
		}
	}

	a.lintReports = java.BuildModuleLintReportZips(ctx, depSets, validations)
}
}


func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath {
func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath {
+0 −14
Original line number Original line Diff line number Diff line
@@ -2612,13 +2612,6 @@ func (a *Import) JacocoReportClassesFile() android.Path {
	return nil
	return nil
}
}


func (j *Import) getStrictUpdatabilityLinting() bool {
	return false
}

func (j *Import) setStrictUpdatabilityLinting(bool) {
}

func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
	ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs.GetOrDefault(ctx, nil)...)
	ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs.GetOrDefault(ctx, nil)...)
@@ -3098,13 +3091,6 @@ func (j *DexImport) IsInstallable() bool {
	return true
	return true
}
}


func (j *DexImport) getStrictUpdatabilityLinting() bool {
	return false
}

func (j *DexImport) setStrictUpdatabilityLinting(bool) {
}

func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	if len(j.properties.Jars) != 1 {
	if len(j.properties.Jars) != 1 {
		ctx.PropertyErrorf("jars", "exactly one jar must be provided")
		ctx.PropertyErrorf("jars", "exactly one jar must be provided")
+80 −82
Original line number Original line Diff line number Diff line
@@ -100,18 +100,12 @@ type linter struct {
	buildModuleReportZip bool
	buildModuleReportZip bool
}
}


type LintDepSetsIntf interface {
	// Methods used to propagate strict_updatability_linting values.
	GetStrictUpdatabilityLinting() bool
	SetStrictUpdatabilityLinting(bool)
}

type LintDepSets struct {
type LintDepSets struct {
	HTML, Text, XML *android.DepSet[android.Path]
	HTML, Text, XML, Baseline *android.DepSet[android.Path]
}
}


type LintDepSetsBuilder struct {
type LintDepSetsBuilder struct {
	HTML, Text, XML *android.DepSetBuilder[android.Path]
	HTML, Text, XML, Baseline *android.DepSetBuilder[android.Path]
}
}


func NewLintDepSetBuilder() LintDepSetsBuilder {
func NewLintDepSetBuilder() LintDepSetsBuilder {
@@ -119,13 +113,17 @@ func NewLintDepSetBuilder() LintDepSetsBuilder {
		HTML:     android.NewDepSetBuilder[android.Path](android.POSTORDER),
		HTML:     android.NewDepSetBuilder[android.Path](android.POSTORDER),
		Text:     android.NewDepSetBuilder[android.Path](android.POSTORDER),
		Text:     android.NewDepSetBuilder[android.Path](android.POSTORDER),
		XML:      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.HTML.Direct(html)
	l.Text.Direct(text)
	l.Text.Direct(text)
	l.XML.Direct(xml)
	l.XML.Direct(xml)
	if baseline.Valid() {
		l.Baseline.Direct(baseline.Path())
	}
	return l
	return l
}
}


@@ -139,6 +137,9 @@ func (l LintDepSetsBuilder) Transitive(info *LintInfo) LintDepSetsBuilder {
	if info.TransitiveXML != nil {
	if info.TransitiveXML != nil {
		l.XML.Transitive(info.TransitiveXML)
		l.XML.Transitive(info.TransitiveXML)
	}
	}
	if info.TransitiveBaseline != nil {
		l.Baseline.Transitive(info.TransitiveBaseline)
	}
	return l
	return l
}
}


@@ -147,6 +148,7 @@ func (l LintDepSetsBuilder) Build() LintDepSets {
		HTML:     l.HTML.Build(),
		HTML:     l.HTML.Build(),
		Text:     l.Text.Build(),
		Text:     l.Text.Build(),
		XML:      l.XML.Build(),
		XML:      l.XML.Build(),
		Baseline: l.Baseline.Build(),
	}
	}
}
}


@@ -194,16 +196,6 @@ var allLintDatabasefiles = map[android.SdkKind]lintDatabaseFiles{
	},
	},
}
}


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]()
var LintProvider = blueprint.NewProvider[*LintInfo]()


type LintInfo struct {
type LintInfo struct {
@@ -215,6 +207,7 @@ type LintInfo struct {
	TransitiveHTML     *android.DepSet[android.Path]
	TransitiveHTML     *android.DepSet[android.Path]
	TransitiveText     *android.DepSet[android.Path]
	TransitiveText     *android.DepSet[android.Path]
	TransitiveXML      *android.DepSet[android.Path]
	TransitiveXML      *android.DepSet[android.Path]
	TransitiveBaseline *android.DepSet[android.Path]
}
}


func (l *linter) enabled() bool {
func (l *linter) enabled() bool {
@@ -250,7 +243,9 @@ func lintRBEExecStrategy(ctx android.ModuleContext) string {
	return ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
	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")
	projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml")
	// Lint looks for a lint.xml file next to the project.xml file, give it one.
	// Lint looks for a lint.xml file next to the project.xml file, give it one.
	configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml")
	configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml")
@@ -313,12 +308,10 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru
	cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
	cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
	cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_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.
		// Verify the module does not baseline issues that endanger safe updatability.
		if l.properties.Lint.Baseline_filename != nil {
		strictUpdatabilityChecksOutputFile := VerifyStrictUpdatabilityChecks(ctx, baselines)
			cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
		cmd.Validation(strictUpdatabilityChecksOutputFile)
			cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks)
		}
	}
	}


	return lintPaths{
	return lintPaths{
@@ -330,6 +323,22 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru


}
}


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
// 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.
// 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 {
func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.WritablePath {
@@ -399,6 +408,26 @@ func (l *linter) lint(ctx android.ModuleContext) {
	l.extraLintCheckJars = append(l.extraLintCheckJars, android.PathForSource(ctx,
	l.extraLintCheckJars = append(l.extraLintCheckJars, android.PathForSource(ctx,
		"prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar"))
		"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).
	rule := android.NewRuleBuilder(pctx, ctx).
		Sbox(android.PathForModuleOut(ctx, "lint"),
		Sbox(android.PathForModuleOut(ctx, "lint"),
			android.PathForModuleOut(ctx, "lint.sbox.textproto")).
			android.PathForModuleOut(ctx, "lint.sbox.textproto")).
@@ -425,22 +454,9 @@ func (l *linter) lint(ctx android.ModuleContext) {
	srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp")
	srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp")
	rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList).Implicits(l.compile_data)
	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("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
	rule.Command().Text("mkdir -p").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 @@ func (l *linter) lint(ctx android.ModuleContext) {
		cmd.FlagWithArg("--check ", checkOnly)
		cmd.FlagWithArg("--check ", checkOnly)
	}
	}


	if l.properties.Lint.Baseline_filename != nil {
	if baseline.Valid() {
		cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
		cmd.FlagWithInput("--baseline ", baseline.Path())
	}
	}


	cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline)
	cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline)
@@ -529,10 +545,11 @@ func (l *linter) lint(ctx android.ModuleContext) {
		TransitiveHTML:     depSets.HTML,
		TransitiveHTML:     depSets.HTML,
		TransitiveText:     depSets.Text,
		TransitiveText:     depSets.Text,
		TransitiveXML:      depSets.XML,
		TransitiveXML:      depSets.XML,
		TransitiveBaseline: depSets.Baseline,
	})
	})


	if l.buildModuleReportZip {
	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.
	// Create a per-module phony target to run the lint check.
@@ -542,7 +559,7 @@ func (l *linter) lint(ctx android.ModuleContext) {
	ctx.SetOutputFiles(android.Paths{xml}, ".lint")
	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())
	htmlList := android.SortedUniquePaths(depSets.HTML.ToList())
	textList := android.SortedUniquePaths(depSets.Text.ToList())
	textList := android.SortedUniquePaths(depSets.Text.ToList())
	xmlList := android.SortedUniquePaths(depSets.XML.ToList())
	xmlList := android.SortedUniquePaths(depSets.XML.ToList())
@@ -552,13 +569,13 @@ func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) a
	}
	}


	htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
	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")
	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")
	xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
	lintZip(ctx, xmlList, xmlZip)
	lintZip(ctx, xmlList, xmlZip, validations)


	return android.Paths{htmlZip, textZip, xmlZip}
	return android.Paths{htmlZip, textZip, xmlZip}
}
}
@@ -668,7 +685,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
			}
			}
		}
		}


		lintZip(ctx, paths, outputPath)
		lintZip(ctx, paths, outputPath, nil)
	}
	}


	l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
	l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
@@ -697,17 +714,9 @@ var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil)
func init() {
func init() {
	android.RegisterParallelSingletonType("lint",
	android.RegisterParallelSingletonType("lint",
		func() android.Singleton { return &lintSingleton{} })
		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))
	paths = android.SortedUniquePaths(android.CopyOfPaths(paths))


	sort.Slice(paths, func(i, j int) bool {
	sort.Slice(paths, func(i, j int) bool {
@@ -719,19 +728,8 @@ func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android
	rule.Command().BuiltTool("soong_zip").
	rule.Command().BuiltTool("soong_zip").
		FlagWithOutput("-o ", outputPath).
		FlagWithOutput("-o ", outputPath).
		FlagWithArg("-C ", android.PathForIntermediates(ctx).String()).
		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())
	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)
			}
		})
	}
}
Loading