Skip to content

Commit

Permalink
Added test variants to the source sets.
Browse files Browse the repository at this point in the history
Changes:
- Updated AndroidUtils to populate all fields individually so failure in retrieval of one property won't lead to the collapse of whole source set.
- Added android resource directories only if the variant is not a unit test
- Updated GradleApiConnectorTest#testAndroidSourceSets to consider the all the test variants and their dependencies
- Addressed checkstyle issues
  • Loading branch information
Tanish-Ranjan committed Sep 5, 2024
1 parent 539099f commit 47dfa24
Show file tree
Hide file tree
Showing 2 changed files with 241 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ public static List<GradleSourceSet> getBuildVariantsAsGradleSourceSets(Project p
try {
Set<Object> variants = (Set<Object>) invokeMethod(androidExtension, methodName);
for (Object variant : variants) {
GradleSourceSet sourceSet = convertVariantToGradleSourceSet(project, variant);
GradleSourceSet sourceSet =
convertVariantToGradleSourceSet(project, variant, sourceSets, false);
if (sourceSet == null) {
continue;
}
Expand All @@ -116,9 +117,15 @@ public static List<GradleSourceSet> getBuildVariantsAsGradleSourceSets(Project p
*
* @param project Gradle project to populate GradleSourceSet properties
* @param variant Android Build Variant object to populate GradleSourceSet properties
* @param sourceSets List of source sets to which test variants will be added
* @param isUnitTest Indicates if the given variant is a unit test variant
*/
@SuppressWarnings("unchecked")
private static GradleSourceSet convertVariantToGradleSourceSet(Project project, Object variant) {
private static GradleSourceSet convertVariantToGradleSourceSet(
Project project,
Object variant,
List<GradleSourceSet> sourceSets,
boolean isUnitTest
) {

try {

Expand Down Expand Up @@ -156,8 +163,57 @@ private static GradleSourceSet convertVariantToGradleSourceSet(Project project,
gradleSourceSet.setDisplayName(displayName);

// module dependencies
Set<GradleModuleDependency> moduleDependencies =
AndroidDependencyCollector.getModuleDependencies(project, variant);
addModuleDependencies(gradleSourceSet, project, variant);

// source and resource
addSourceAndResources(gradleSourceSet, variant, isUnitTest);

// resource outputs
addResourceOutputs(gradleSourceSet, variant, isUnitTest);

List<String> compilerArgs = new ArrayList<>();

// generated sources and source outputs
addGeneratedSourceAndSourceOutputs(gradleSourceSet, variant, compilerArgs);

// classpath
addClasspath(gradleSourceSet, variant);

// Archive output dirs (not relevant in case of android build variants)
gradleSourceSet.setArchiveOutputFiles(new HashMap<>());

// has tests
addTests(gradleSourceSet, project, variant, sourceSets);

// extensions
addExtensions(gradleSourceSet, compilerArgs);

return gradleSourceSet;

} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
return null;
}

}

/**
* Add module dependencies to the given GradleSourceSet.
*
* @param gradleSourceSet Instance of DefaultGradleSourceSet
* @param project Instance of Project
* @param variant Instance of Build Variant
*/
@SuppressWarnings("unchecked")
private static void addModuleDependencies(
DefaultGradleSourceSet gradleSourceSet,
Project project,
Object variant
) {

Set<GradleModuleDependency> moduleDependencies =
AndroidDependencyCollector.getModuleDependencies(project, variant);

try {
// add Android SDK
Object androidComponents = getAndroidComponentExtension(project);
if (androidComponents != null) {
Expand All @@ -178,7 +234,7 @@ private static GradleSourceSet convertVariantToGradleSourceSet(Project project,
}
}
// add R.jar file
String taskName = "process" + capitalize(variantName) + "Resources";
String taskName = "process" + capitalize(gradleSourceSet.getSourceSetName()) + "Resources";
Task processResourcesTask = project.getTasks().findByName(taskName);
if (processResourcesTask != null) {
Object output = invokeMethod(processResourcesTask, "getRClassOutputJar");
Expand All @@ -188,53 +244,116 @@ private static GradleSourceSet convertVariantToGradleSourceSet(Project project,
moduleDependencies.add(mockModuleDependency(jarFile.toURI()));
}
}
gradleSourceSet.setModuleDependencies(moduleDependencies);
} catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
// do nothing
}

// source and resource
gradleSourceSet.setModuleDependencies(moduleDependencies);

}

/**
* Add source and resource directories to the given GradleSourceSet.
*
* @param gradleSourceSet Instance of DefaultGradleSourceSet
* @param variant Instance of Build Variant
* @param isUnitTest Indicates if the given variant is a unit test variant
*/
@SuppressWarnings("unchecked")
private static void addSourceAndResources(
DefaultGradleSourceSet gradleSourceSet,
Object variant,
boolean isUnitTest
) {

Set<File> sourceDirs = new HashSet<>();
Set<File> resourceDirs = new HashSet<>();

try {
Object sourceSets = getProperty(variant, "sourceSets");
Set<File> sourceDirs = new HashSet<>();
Set<File> resourceDirs = new HashSet<>();
if (sourceSets instanceof Iterable) {
for (Object sourceSet : (Iterable<?>) sourceSets) {
Set<File> javaDirectories =
(Set<File>) getProperty(sourceSet, "javaDirectories");
Set<File> resDirectories =
(Set<File>) getProperty(sourceSet, "resDirectories");
Set<File> resourceDirectories =
(Set<File>) getProperty(sourceSet, "resourcesDirectories");
sourceDirs.addAll(javaDirectories);
resourceDirs.addAll(resDirectories);
resourceDirs.addAll(resourceDirectories);
if (!isUnitTest) {
resourceDirs.addAll((Set<File>) getProperty(sourceSet, "resDirectories"));
}
resourceDirs.addAll((Set<File>) getProperty(sourceSet, "resourcesDirectories"));
}
}
gradleSourceSet.setSourceDirs(sourceDirs);
gradleSourceSet.setResourceDirs(resourceDirs);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
// do nothing
}

// resource outputs
Set<File> resourceOutputs = new HashSet<>();
gradleSourceSet.setSourceDirs(sourceDirs);
gradleSourceSet.setResourceDirs(resourceDirs);

}

/**
* Add resource output directories to the given GradleSourceSet.
*
* @param gradleSourceSet Instance of DefaultGradleSourceSet
* @param variant Instance of Build Variant
* @param isUnitTest Indicates if the given variant is a unit test variant
*/
@SuppressWarnings("unchecked")
private static void addResourceOutputs(
DefaultGradleSourceSet gradleSourceSet,
Object variant,
boolean isUnitTest
) {

Set<File> resourceOutputs = new HashSet<>();

try {
Provider<Task> resourceProvider =
(Provider<Task>) getProperty(variant, "processJavaResourcesProvider");
if (resourceProvider != null) {
Task resTask = resourceProvider.get();
File outputDir = (File) invokeMethod(resTask, "getDestinationDir");
resourceOutputs.add(outputDir);
}
Provider<Task> resProvider =
(Provider<Task>) getProperty(variant, "mergeResourcesProvider");
if (resProvider != null) {
Task resTask = resProvider.get();
Object outputDir = invokeMethod(resTask, "getOutputDir");
File output = ((Provider<File>) invokeMethod(outputDir, "getAsFile")).get();
resourceOutputs.add(output);

if (!isUnitTest) {
Provider<Task> resProvider =
(Provider<Task>) getProperty(variant, "mergeResourcesProvider");
if (resProvider != null) {
Task resTask = resProvider.get();
Object outputDir = invokeMethod(resTask, "getOutputDir");
File output = ((Provider<File>) invokeMethod(outputDir, "getAsFile")).get();
resourceOutputs.add(output);
}
}
gradleSourceSet.setResourceOutputDirs(resourceOutputs);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
// do nothing
}

// generated sources and source outputs
Set<File> generatedSources = new HashSet<>();
Set<File> sourceOutputs = new HashSet<>();
gradleSourceSet.setResourceOutputDirs(resourceOutputs);

}

/**
* Add source output and generated source output directories to the given GradleSourceSet.
*
* @param gradleSourceSet Instance of DefaultGradleSourceSet
* @param variant Instance of Build Variant
* @param compilerArgs List to be populated from the java compiler arguments.
*/
@SuppressWarnings("unchecked")
private static void addGeneratedSourceAndSourceOutputs(
DefaultGradleSourceSet gradleSourceSet,
Object variant,
List<String> compilerArgs
) {

Set<File> generatedSources = new HashSet<>();
Set<File> sourceOutputs = new HashSet<>();

try {
Provider<Task> javaCompileProvider =
(Provider<Task>) getProperty(variant, "javaCompileProvider");
List<String> compilerArgs = new ArrayList<>();
if (javaCompileProvider != null) {
Task javaCompileTask = javaCompileProvider.get();

Expand All @@ -248,7 +367,7 @@ private static GradleSourceSet convertVariantToGradleSourceSet(Project project,

// generated = compile source - source
for (File compileSource : compileSources) {
boolean inSourceDir = sourceDirs.stream()
boolean inSourceDir = gradleSourceSet.getSourceDirs().stream()
.anyMatch(dir -> compileSource.getAbsolutePath().startsWith(dir.getAbsolutePath()));
if (inSourceDir) {
continue;
Expand All @@ -261,43 +380,99 @@ private static GradleSourceSet convertVariantToGradleSourceSet(Project project,
generatedSources.add(compileSource);
}
}
gradleSourceSet.setGeneratedSourceDirs(generatedSources);
gradleSourceSet.setSourceOutputDirs(sourceOutputs);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
// do nothing
}

// classpath
gradleSourceSet.setGeneratedSourceDirs(generatedSources);
gradleSourceSet.setSourceOutputDirs(sourceOutputs);

}

/**
* Add classpath files to the given GradleSourceSet.
*
* @param gradleSourceSet Instance of DefaultGradleSourceSet
* @param variant Instance of Build Variant
*/
@SuppressWarnings("unchecked")
private static void addClasspath(DefaultGradleSourceSet gradleSourceSet, Object variant) {

Set<File> classpathFiles = new HashSet<>();

try {
Object compileConfig = invokeMethod(variant, "getCompileConfiguration");
Set<File> classpathFiles = (Set<File>) invokeMethod(compileConfig, "getFiles");
gradleSourceSet.setCompileClasspath(new LinkedList<>(classpathFiles));
classpathFiles.addAll((Set<File>) invokeMethod(compileConfig, "getFiles"));
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
// do nothing
}

// Archive output dirs (not relevant in case of android build variants)
gradleSourceSet.setArchiveOutputFiles(new HashMap<>());
gradleSourceSet.setCompileClasspath(new LinkedList<>(classpathFiles));

// has tests
}

/**
* Add classpath files to the given GradleSourceSet.
*
* @param gradleSourceSet Instance of DefaultGradleSourceSet
* @param project Instance of Project
* @param variant Instance of Build Variant
* @param sourceSets List of source sets to which test variants will be added
*/
private static void addTests(
DefaultGradleSourceSet gradleSourceSet,
Project project,
Object variant,
List<GradleSourceSet> sourceSets
) {
try {
Object unitTestVariant = invokeMethod(variant, "getUnitTestVariant");
Object testVariant = invokeMethod(variant, "getTestVariant");
gradleSourceSet.setHasTests(unitTestVariant != null || testVariant != null);

// extensions
Map<String, LanguageExtension> extensions = new HashMap<>();
boolean isJavaSupported = Arrays.stream(SourceSetUtils.getSupportedLanguages())
.anyMatch(l -> Objects.equals(l, SupportedLanguages.JAVA.getBspName()));
if (isJavaSupported) {
DefaultJavaExtension extension = new DefaultJavaExtension();

extension.setCompilerArgs(compilerArgs);
extension.setSourceCompatibility(getSourceCompatibility(compilerArgs));
extension.setTargetCompatibility(getTargetCompatibility(compilerArgs));

extensions.put(SupportedLanguages.JAVA.getBspName(), extension);
if (unitTestVariant != null) {
GradleSourceSet unitTestSourceSet =
convertVariantToGradleSourceSet(project, unitTestVariant, sourceSets, true);
if (unitTestSourceSet != null) {
sourceSets.add(unitTestSourceSet);
}
}
gradleSourceSet.setExtensions(extensions);

return gradleSourceSet;

if (testVariant != null) {
GradleSourceSet androidTestSourceSet =
convertVariantToGradleSourceSet(project, testVariant, sourceSets, false);
if (androidTestSourceSet != null) {
sourceSets.add(androidTestSourceSet);
}
}
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
return null;
// do nothing
}
}

/**
* Add language extension to the given GradleSourceSet.
*
* @param gradleSourceSet Instance of DefaultGradleSourceSet
* @param compilerArgs List of compiler arguments needed to build the language extension.
*/
private static void addExtensions(
DefaultGradleSourceSet gradleSourceSet,
List<String> compilerArgs
) {
Map<String, LanguageExtension> extensions = new HashMap<>();
boolean isJavaSupported = Arrays.stream(SourceSetUtils.getSupportedLanguages())
.anyMatch(l -> Objects.equals(l, SupportedLanguages.JAVA.getBspName()));
if (isJavaSupported) {
DefaultJavaExtension extension = new DefaultJavaExtension();

extension.setCompilerArgs(compilerArgs);
extension.setSourceCompatibility(getSourceCompatibility(compilerArgs));
extension.setTargetCompatibility(getTargetCompatibility(compilerArgs));

extensions.put(SupportedLanguages.JAVA.getBspName(), extension);
}
gradleSourceSet.setExtensions(extensions);
}

/**
Expand Down Expand Up @@ -426,6 +601,7 @@ private static Object invokeMethod(Object object, String methodName)
}

// region TODO: Duplicate code from JavaLanguageModelBuilder

/**
* Get the compilation arguments of the build variant.
*/
Expand Down
Loading

0 comments on commit 47dfa24

Please sign in to comment.