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

Commit a96a7b1e authored by Jihoon Kang's avatar Jihoon Kang
Browse files

Remove naming conventioned based file sorting in java_api_library

With api_files property being removed from java_api_library, all api
files are passed to java_api_library via java_api_contribution, which
provide api_surface information. Instead of relying on the naming
convention of the api files, java_api_library can utilize this
information to sort the api files from narrower api scope to the wider
api scope.

Test: m --build-from-text-stub
Bug: 295429988
Change-Id: Idd832778833c072c6b7e9d1f775533e5f4e2af00
parent 6be0f006
Loading
Loading
Loading
Loading
+18 −23
Original line number Diff line number Diff line
@@ -1814,31 +1814,22 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
	}
}

// API signature file names sorted from
// the narrowest api scope to the widest api scope
var scopeOrderedSourceFileNames = allApiScopes.Strings(
	func(s *apiScope) string { return s.apiFilePrefix + "current.txt" })
// Map where key is the api scope name and value is the int value
// representing the order of the api scope, narrowest to the widest
var scopeOrderMap = allApiScopes.MapToIndex(
	func(s *apiScope) string { return s.name })

func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) android.Paths {
	var sortedSrcFiles android.Paths

	for i, apiScope := range allApiScopes {
func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo {
	for _, srcFileInfo := range srcFilesInfo {
			if srcFileInfo.ApiFile.Base() == scopeOrderedSourceFileNames[i] || srcFileInfo.ApiSurface == apiScope.name {
				sortedSrcFiles = append(sortedSrcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String()))
			}
		}
		if srcFileInfo.ApiSurface == "" {
			ctx.ModuleErrorf("Api surface not defined for the associated api file %s", srcFileInfo.ApiFile)
		}

	if len(srcFilesInfo) != len(sortedSrcFiles) {
		var srcFiles android.Paths
		for _, srcFileInfo := range srcFilesInfo {
			srcFiles = append(srcFiles, srcFileInfo.ApiFile)
		}
		ctx.ModuleErrorf("Unrecognizable source file found within %s", srcFiles)
	}
	sort.Slice(srcFilesInfo, func(i, j int) bool {
		return scopeOrderMap[srcFilesInfo[i].ApiSurface] < scopeOrderMap[srcFilesInfo[j].ApiSurface]
	})

	return sortedSrcFiles
	return srcFilesInfo
}

func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1881,7 +1872,11 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		}
	})

	srcFiles := al.sortApiFilesByApiScope(ctx, srcFilesInfo)
	srcFilesInfo = al.sortApiFilesByApiScope(ctx, srcFilesInfo)
	var srcFiles android.Paths
	for _, srcFileInfo := range srcFilesInfo {
		srcFiles = append(srcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String()))
	}

	if srcFiles == nil && !ctx.Config().AllowMissingDependencies() {
		ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
+27 −0
Original line number Diff line number Diff line
@@ -2398,3 +2398,30 @@ func TestJavaApiContributionImport(t *testing.T) {
	sourceFilesFlag := "--source-files current.txt"
	android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
}

func TestJavaApiLibraryApiFilesSorting(t *testing.T) {
	ctx, _ := testJava(t, `
		java_api_library {
			name: "foo",
			api_contributions: [
				"system-server-api-stubs-docs-non-updatable.api.contribution",
				"test-api-stubs-docs-non-updatable.api.contribution",
				"system-api-stubs-docs-non-updatable.api.contribution",
				"module-lib-api-stubs-docs-non-updatable.api.contribution",
				"api-stubs-docs-non-updatable.api.contribution",
			],
		}
	`)
	m := ctx.ModuleForTests("foo", "android_common")
	manifest := m.Output("metalava.sbox.textproto")
	sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
	manifestCommand := sboxProto.Commands[0].GetCommand()

	// Api files are sorted from the narrowest api scope to the widest api scope.
	// test api and module lib api surface do not have subset/superset relationship,
	// but they will never be passed as inputs at the same time.
	sourceFilesFlag := "--source-files default/java/api/current.txt " +
		"default/java/api/system-current.txt default/java/api/test-current.txt " +
		"default/java/api/module-lib-current.txt default/java/api/system-server-current.txt"
	android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag)
}
+11 −0
Original line number Diff line number Diff line
@@ -286,6 +286,17 @@ func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string {
	return list
}

// Method that maps the apiScopes properties to the index of each apiScopes elements.
// apiScopes property to be used as the key can be specified with the input accessor.
// Only a string property of apiScope can be used as the key of the map.
func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]int {
	ret := make(map[string]int)
	for i, scope := range scopes {
		ret[accessor(scope)] = i
	}
	return ret
}

var (
	scopeByName    = make(map[string]*apiScope)
	allScopeNames  []string