in aswb/src/com/google/idea/blaze/android/sync/projectstructure/BlazeAndroidProjectStructureSyncer.java [102:224]
public static void updateProjectStructure(
Project project,
BlazeContext context,
ProjectViewSet projectViewSet,
BlazeProjectData blazeProjectData,
@Nullable BlazeProjectData projectDataFromPreviousSync,
BlazeSyncPlugin.ModuleEditor moduleEditor,
Module workspaceModule,
ModifiableRootModel workspaceModifiableModel,
boolean isAndroidWorkspace) {
if (!isAndroidWorkspace) {
AndroidFacetModuleCustomizer.removeAndroidFacet(workspaceModule);
// Workspace type should always be ANDROID as long as the blaze android plugin is present.
log.error(
"No android workspace found for project \""
+ project.getName()
+ "\". Removing AndroidFacet from workspace module.");
return;
}
AndroidFacetModuleCustomizer.createAndroidFacet(workspaceModule, false);
BlazeAndroidSyncData syncData = blazeProjectData.getSyncState().get(BlazeAndroidSyncData.class);
if (syncData == null) {
if (projectDataFromPreviousSync != null) {
// If the prior sync had android sync data, but the current one doesn't, then something
// really bad happened. Nothing's gonna work until this is fixed.
context.output(
PrintOutput.error(
"The IDE was not able to retrieve the necessary information from Blaze. Many"
+ " android specific features may not work. Please try [Blaze > Sync > Sync"
+ " project with BUILD files] again."));
}
return;
}
AndroidSdkPlatform androidSdkPlatform = syncData.androidSdkPlatform;
if (androidSdkPlatform == null) {
return;
}
// We need to create android resource modules for all targets excluding those that end up
// getting associated with the workspace module.
List<AndroidResourceModule> nonWorkspaceResourceModules =
syncData.importResult.androidResourceModules.stream()
.filter(m -> !WORKSPACE_RESOURCES_TARGET_KEY.equals(m.targetKey))
.collect(Collectors.toList());
int totalOrderEntries = 0;
Set<File> existingRoots = Sets.newHashSet();
ArtifactLocationDecoder artifactLocationDecoder = blazeProjectData.getArtifactLocationDecoder();
LibraryTable libraryTable = LibraryTablesRegistrar.getInstance().getLibraryTable(project);
for (AndroidResourceModule androidResourceModule : nonWorkspaceResourceModules) {
String moduleName = moduleNameForAndroidModule(androidResourceModule.targetKey);
Module module = moduleEditor.createModule(moduleName, StdModuleTypes.JAVA);
TargetIdeInfo target = blazeProjectData.getTargetMap().get(androidResourceModule.targetKey);
Verify.verifyNotNull(target);
boolean isApp =
target.kindIsOneOf(RuleTypes.ANDROID_BINARY.getKind(), RuleTypes.ANDROID_TEST.getKind());
AndroidFacetModuleCustomizer.createAndroidFacet(module, isApp);
AndroidIdeInfo androidIdeInfo = Verify.verifyNotNull(target.getAndroidIdeInfo());
ArrayList<File> newRoots =
new ArrayList<>(
OutputArtifactResolver.resolveAll(
project, artifactLocationDecoder, androidResourceModule.resources));
File moduleDirectory =
moduleDirectoryForAndroidTarget(WorkspaceRoot.fromProject(project), target);
File manifest =
manifestFileForAndroidTarget(
project, artifactLocationDecoder, androidIdeInfo, moduleDirectory);
if (manifest != null) {
newRoots.add(manifest);
}
// Multiple libraries may end up pointing to files from the same res folder. If we've already
// added something as a root, then we skip registering it as a root in another res module.
// This works since our dependency graph is cyclic via the workspace module.
newRoots.removeAll(existingRoots);
existingRoots.addAll(newRoots);
ModifiableRootModel modifiableRootModel = moduleEditor.editModule(module);
ResourceModuleContentRootCustomizer.setupContentRoots(modifiableRootModel, newRoots);
modifiableRootModel.addModuleOrderEntry(workspaceModule);
++totalOrderEntries;
// Add a dependency from the workspace to the resource module
ModuleOrderEntry orderEntry = workspaceModifiableModel.addModuleOrderEntry(module);
orderEntry.setExported(true);
++totalOrderEntries;
// The workspace module depends on all libraries (including aars). All resource modules
// depend on the workspace module, and hence transitively depend on all the libraries. As a
// result, there is no need to explicitly attach libraries to each resource module. Doing
// so only increases the number of order entries, which exacerbates issues like b/187413558
// where the Kotlin plugin does calculations proportional to the # of order entries.
if (attachAarForResourceModule.getValue()) {
for (String libraryName : androidResourceModule.resourceLibraryKeys) {
Library lib = libraryTable.getLibraryByName(libraryName);
if (lib == null) {
String message =
String.format(
"Could not find library '%s' for module '%s'. Re-syncing might fix this issue.",
libraryName, moduleName);
log.warn(message);
context.output(PrintOutput.log(message));
} else {
modifiableRootModel.addLibraryEntry(lib);
}
}
}
}
int allowedGenResources = projectViewSet.listItems(GeneratedAndroidResourcesSection.KEY).size();
context.output(
PrintOutput.log(
String.format(
"Android resource module count: %d, order entries: %d, generated resources: %d",
syncData.importResult.androidResourceModules.size(),
totalOrderEntries,
allowedGenResources)));
}