bazelbuild / intellij

IntelliJ plugin for Bazel projects
https://ij.bazel.build/
Apache License 2.0
761 stars 303 forks source link

Support Jetpack Compose previews in Android Studio #2765

Open alexjlockwood opened 3 years ago

alexjlockwood commented 3 years ago

Currently when you import an Android Studio project that builds an app using Jetpack Compose UI, it will fail to display compose previews.

The expected behavior is that Android Studio should recognize when a Kotlin file contains a composable @Preview and open the compose designer plugin shown here.

idanakav commented 2 years ago

I was recently experimenting with the compose preview and was able to get it working locally, this would require a couple of changes upstream.

compsepreview

The issues I've found:

  1. Wrong ComposeViewAdapter is being used

    There are two compose namespaces (see definition) Bazel would try to load androidx.compose.ui.tooling.preview.ComposeViewAdapter instead of androidx.compose.ui.tooling.ComposeViewAdapter due to BlazeModuleSystem::getResolvedDependency unable to resolve dependencies.

    The logic in getResolvedDependency relies on MavenArtifactLocator to do the lookup but the plugin as for today does not have any MavenArtifactLocator extensions registered.

  2. Missing classes in the class path of ModuleClassLoader ModuleClassLoader is responsible for initializing ComposeViewAdapter and required to have specific classes in the class path. Currently BlazeClassJarProvider which is responsible for providing the external libraries jars to the class path is returning nothing for the .workspace module, the straightforward solution is to include all of the libraries in the workspace module case.

  3. External libraries resources can't be looked up This is somewhat related to the previous issue in the way that android resources are not available in the class path of ModuleClassLoader but in this case the issue is caused because of the existing logic in BlazeAndroidWorkspaceImporter::createAarLibrary is creating the AarLibrary models with an empty package name. The solution here is to somehow infer the package name from the actual aar (perhaps reading them from the manifest files?)

I'm more than happy to give it a shot and create the PRs with my proposals it would be great though if someone who is more familiar with the codebase could give a few insights on the solutions I proposed.

vsiva commented 2 years ago

I work on the Android Studio for Blaze team, so I'm aware of some of the issues, but we do not have the bandwidth to officially support this for Bazel users. But here are some pointers:

  1. MavenArtifactLocator: Internally at Google, we don't use Maven. So what we've done is introduce this layer of abstraction called MavenArtifactLocator. We recognize certain known artifacts, and redirect them to the target where they are checked into source control. For Bazel, I have no idea how different companies are handling it, but one option is to write an ArtifactLocator that picks artifacts from Maven (just like Gradle would do).

  2. ModuleClassLoader: Some of the changes we did here only applied to Blaze, so they aren't in the open source Bazel plugin, but the issues are probably minimal. Perhaps the Bazel team may help here. The expectation is that the class loader is supposed to provide the .class file corresponding to any fully qualified class name. The approach we follow internally now is to build deploy jars corresponding to all android_binaries, and use those deploy jars to provide the classes.

  3. AarLibrary instances should be created from BlazeAndroidWorkspaceImporter with the correct package name. If they aren't, then perhaps there is a Blaze vs Bazel difference.

Even after all of this, there are some more gotchas (mainly around R class resolution). Re: PRs, I think a solution for the MavenArtifactLocator would be fairly isolated and possible to accept, but the other two are somewhat involved and would need time from someone in the bazel team to review and verify that everything is ok.

Bencodes commented 1 year ago

@sgowroji would you be able to help triage this one?

pswaminathan commented 1 year ago

@idanakav are you currently using this/is it still working? I cherry picked your branch into the latest release, and I'm getting errors like "Cannot obtain the application ID."

colinrgodsey commented 1 year ago

Have a working solution for Dolphin: https://github.com/ergatta/intellij/pull/1