diff --git a/app/src/main/assets/data/common/tooling-api-all.jar b/app/src/main/assets/data/common/tooling-api-all.jar index 418c9a7c8..d2254a036 100644 Binary files a/app/src/main/assets/data/common/tooling-api-all.jar and b/app/src/main/assets/data/common/tooling-api-all.jar differ diff --git a/build-tools/javac-services/src/main/java/com/itsaky/androidide/javac/services/NBClassFinder.java b/build-tools/javac-services/src/main/java/com/itsaky/androidide/javac/services/NBClassFinder.java index 98ffaf00d..18ea35060 100644 --- a/build-tools/javac-services/src/main/java/com/itsaky/androidide/javac/services/NBClassFinder.java +++ b/build-tools/javac-services/src/main/java/com/itsaky/androidide/javac/services/NBClassFinder.java @@ -108,17 +108,16 @@ public class NBClassFinder extends ClassFinder { throw constr.newInstance( sym, (Supplier) - () -> { - return diagFactory.create( - log.currentSource(), - new SimpleDiagnosticPosition(0), - DiagnosticInfo.of( - DiagnosticType.ERROR, - "compiler", - "cant.resolve", - "package", - "java.lang")); - }, + () -> + diagFactory.create( + log.currentSource(), + new SimpleDiagnosticPosition(0), + DiagnosticInfo.of( + DiagnosticType.ERROR, + "compiler", + "cant.resolve", + "package", + "java.lang")), dcfh); } catch (ClassNotFoundException | NoSuchMethodException diff --git a/build-tools/jdt/build.gradle b/build-tools/jdt/build.gradle index 59e58119b..84d4dfed0 100644 --- a/build-tools/jdt/build.gradle +++ b/build-tools/jdt/build.gradle @@ -3,6 +3,6 @@ plugins { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = rootProject.ext.javaSourceVersion + targetCompatibility = rootProject.ext.javaTargetVersion } \ No newline at end of file diff --git a/build-tools/projects/src/main/java/com/itsaky/androidide/projects/api/JavaModule.kt b/build-tools/projects/src/main/java/com/itsaky/androidide/projects/api/JavaModule.kt index 4f640bcf3..459d33543 100644 --- a/build-tools/projects/src/main/java/com/itsaky/androidide/projects/api/JavaModule.kt +++ b/build-tools/projects/src/main/java/com/itsaky/androidide/projects/api/JavaModule.kt @@ -23,6 +23,7 @@ import com.itsaky.androidide.tooling.api.IProject.Type.Java import com.itsaky.androidide.tooling.api.model.GradleTask import com.itsaky.androidide.tooling.api.model.JavaContentRoot import com.itsaky.androidide.tooling.api.model.JavaModuleDependency +import com.itsaky.androidide.tooling.api.model.JavaModuleExternalDependency import com.itsaky.androidide.tooling.api.model.JavaModuleProjectDependency import java.io.File @@ -112,13 +113,10 @@ class JavaModule( override fun getCompileClasspaths(): Set { val classpaths = getModuleClasspaths().toMutableSet() getCompileModuleProjects().forEach { classpaths.addAll(it.getCompileClasspaths()) } + classpaths.addAll(getDependencyClasspaths()) return classpaths } - - // TODO IdeaDependency.getExported() always returns false - // Find out its cause and handle exported dependencies here. - // - // Currently transitive dependencies are not included in this. + override fun getCompileModuleProjects(): List { val root = ProjectManager.rootProject ?: return emptyList() return this.dependencies @@ -127,4 +125,8 @@ class JavaModule( .mapNotNull { root.findByPath(it.projectPath) } .filterIsInstance(ModuleProject::class.java) } + + fun getDependencyClasspaths(): Set { + return this.dependencies.filterIsInstance().mapNotNull { it.jarFile }.toHashSet() + } } diff --git a/build-tools/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/ToolingApiImplTest.kt b/build-tools/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/MultiModuleAndroidProjectTest.kt similarity index 92% rename from build-tools/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/ToolingApiImplTest.kt rename to build-tools/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/MultiModuleAndroidProjectTest.kt index 6b378c433..7f9a159d1 100644 --- a/build-tools/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/ToolingApiImplTest.kt +++ b/build-tools/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/MultiModuleAndroidProjectTest.kt @@ -21,8 +21,7 @@ import com.android.builder.model.v2.ide.LibraryType.PROJECT import com.android.builder.model.v2.ide.ProjectType.APPLICATION import com.google.common.truth.Truth.assertThat import com.google.gson.GsonBuilder -import com.itsaky.androidide.tooling.api.IProject -import com.itsaky.androidide.tooling.api.IToolingApiServer +import com.itsaky.androidide.tooling.api.IProject.Type.Gradle import com.itsaky.androidide.tooling.api.messages.InitializeProjectMessage import com.itsaky.androidide.tooling.api.model.AndroidModule import com.itsaky.androidide.tooling.api.model.JavaModule @@ -37,55 +36,42 @@ import org.junit.runners.JUnit4 /** @author Akash Yadav */ @RunWith(JUnit4::class) -class ToolingApiImplTest { +class MultiModuleAndroidProjectTest { @Test fun testProjectInit() { val (server, project) = ToolingApiTestLauncher().launchServer() server.initialize(InitializeProjectMessage(File("../../tests/test-project").absolutePath)).get() - verifyProjectProps(project, server) - } - - private fun verifyProjectProps(project: IProject, server: IToolingApiServer) { assertThat(project).isNotNull() - assertThat(project.type.get()).isEqualTo(IProject.Type.Gradle) + assertThat(project.type.get()).isEqualTo(Gradle) // As the returned project is just a proxy, // project instanceOf IdeGradleProject will always return false - val isInitialized = server.isServerInitialized().get() assertThat(isInitialized).isTrue() - val app = project.findByPath(":app").get() assertThat(app).isNotNull() assertThat(app).isInstanceOf(AndroidModule::class.java) - GsonBuilder().apply { ToolingApiLauncher.configureGson(this) println(create().toJson(app)) } - assertThat((app as AndroidModule).javaCompileOptions).isNotNull() assertThat(app.javaCompileOptions.sourceCompatibility).isEqualTo("11") assertThat(app.javaCompileOptions.targetCompatibility).isEqualTo("11") assertThat(app.javaCompileOptions.javaSourceVersion).isEqualTo("11") assertThat(app.javaCompileOptions.javaBytecodeVersion).isEqualTo("11") assertThat(app.javaCompileOptions.isCoreLibraryDesugaringEnabled).isFalse() - assertThat(app.projectType).isEqualTo(APPLICATION) assertThat(app.packageName).isEqualTo("com.itsaky.test.app") - assertThat(app.viewBindingOptions).isNotNull() assertThat(app.viewBindingOptions!!.isEnabled).isTrue() - // There are always more than 100 tasks in an android module // Also, the tasks must contain the user defined tasks assertThat(app.tasks.size).isAtLeast(100) assertThat(app.tasks.first { it.path == "${app.projectPath}:thisIsATestTask" }).isNotNull() - assertThat(app.libraries).isNotEmpty() // At least one project library assertThat(app.libraryMap.values.filter { it.type == PROJECT }).isNotEmpty() - // :app module includes :java-library as a dependency. But it is not transitive assertThat( app.libraryMap.values.firstOrNull { @@ -95,7 +81,6 @@ class ToolingApiImplTest { } ) .isNull() - val androidLib = project.findByPath(":android-library").get() assertThat(androidLib).isNotNull() assertThat(androidLib).isInstanceOf(AndroidModule::class.java) @@ -110,16 +95,13 @@ class ToolingApiImplTest { } ) .isNotNull() - assertThat(androidLib.javaCompileOptions.javaSourceVersion).isEqualTo("11") assertThat(androidLib.javaCompileOptions.javaBytecodeVersion).isEqualTo("11") - val javaLibrary = project.findByPath(":java-library").get() assertThat(javaLibrary).isNotNull() assertThat(javaLibrary).isInstanceOf(JavaModule::class.java) assertThat((javaLibrary as JavaModule).compilerSettings.javaSourceVersion).isEqualTo("11") assertThat(javaLibrary.compilerSettings.javaBytecodeVersion).isEqualTo("11") - assertThat( javaLibrary.javaDependencies.firstOrNull { it is JavaModuleExternalDependency && @@ -132,14 +114,12 @@ class ToolingApiImplTest { } ) .isNotNull() - assertThat( javaLibrary.javaDependencies.firstOrNull { it is JavaModuleProjectDependency && it.moduleName == "another-java-library" } ) .isNotNull() - // In case we have multiple dependencies with same name but different path val nested = javaLibrary.javaDependencies @@ -147,13 +127,13 @@ class ToolingApiImplTest { .filter { it.moduleName.endsWith("nested-java-library") } assertThat(nested).hasSize(2) assertThat(nested[0].projectPath).isNotEqualTo(nested[1].projectPath) - assertThat(project.findByPath(":does-not-exist").get()).isNull() - val anotherJavaLib = project.findByPath(":another-java-library").get() assertThat(anotherJavaLib).isNotNull() assertThat(anotherJavaLib).isInstanceOf(JavaModule::class.java) assertThat((anotherJavaLib as JavaModule).compilerSettings.javaSourceVersion).isEqualTo("1.8") assertThat(anotherJavaLib.compilerSettings.javaBytecodeVersion).isEqualTo("1.8") + + server.shutdown().get() } } diff --git a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/CompileBatch.java b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/CompileBatch.java index 0222f0404..636f75664 100644 --- a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/CompileBatch.java +++ b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/CompileBatch.java @@ -17,6 +17,13 @@ package com.itsaky.androidide.lsp.java.compiler; +import static com.itsaky.androidide.config.JavacConfigProvider.PROP_ANDROIDIDE_JAVA_HOME; +import static com.itsaky.androidide.config.JavacConfigProvider.disableModules; +import static com.itsaky.androidide.config.JavacConfigProvider.enableModules; +import static com.itsaky.androidide.config.JavacConfigProvider.setLatestSourceVersion; +import static com.itsaky.androidide.config.JavacConfigProvider.setLatestSupportedSourceVersion; +import static com.itsaky.androidide.utils.Environment.JAVA_HOME; + import androidx.annotation.NonNull; import androidx.core.util.Pair; @@ -26,10 +33,11 @@ import com.itsaky.androidide.javac.services.compiler.ReusableBorrow; import com.itsaky.androidide.javac.services.partial.DiagnosticListenerImpl; import com.itsaky.androidide.lsp.java.visitors.MethodRangeScanner; import com.itsaky.androidide.models.Range; +import com.itsaky.androidide.projects.api.AndroidModule; import com.itsaky.androidide.projects.api.ModuleProject; import com.itsaky.androidide.projects.util.StringSearch; +import com.itsaky.androidide.tooling.api.IProject; import com.itsaky.androidide.utils.ClassTrie; -import com.itsaky.androidide.utils.Environment; import com.itsaky.androidide.utils.ILogger; import com.itsaky.androidide.utils.SourceClassTrie; import com.itsaky.androidide.utils.StopWatch; @@ -133,21 +141,18 @@ public class CompileBatch implements AutoCloseable { @NonNull private List options() { List options = new ArrayList<>(); - - // TODO Boot classpath must be different in java projects - // Also, java modules must be enabled in java projects - System.setProperty( - JavacConfigProvider.PROP_ANDROIDIDE_JAVA_HOME, Environment.JAVA_HOME.getAbsolutePath()); - JavacConfigProvider.setLatestSourceVersion(SourceVersion.RELEASE_8); - JavacConfigProvider.setLatestSupportedSourceVersion(SourceVersion.RELEASE_11); - - JavacConfigProvider.disableModules(); - - LOG.debug( - JavacConfigProvider.getJavaHome(), - JavacConfigProvider.isModulesEnabled(), - SourceVersion.latest(), - SourceVersion.latestSupported()); + + // This won't be used if the current module is Android module project + System.setProperty(PROP_ANDROIDIDE_JAVA_HOME, JAVA_HOME.getAbsolutePath()); + if (this.parent.module != null && this.parent.module.getType() == IProject.Type.Android) { + setLatestSourceVersion(SourceVersion.RELEASE_8); + setLatestSupportedSourceVersion(SourceVersion.RELEASE_11); + disableModules(); + } else { + setLatestSourceVersion(SourceVersion.RELEASE_11); + setLatestSupportedSourceVersion(SourceVersion.RELEASE_11); + enableModules(); + } setupCompileOptions(parent.module, options); Collections.addAll(options, "-proc:none", "-g"); diff --git a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/SourceFileManager.java b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/SourceFileManager.java index 482ba2891..d948ce5a3 100644 --- a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/SourceFileManager.java +++ b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/SourceFileManager.java @@ -20,15 +20,15 @@ package com.itsaky.androidide.lsp.java.compiler; import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; -import android.text.TextUtils; - import androidx.annotation.NonNull; import com.blankj.utilcode.util.CloseUtils; +import com.itsaky.androidide.config.JavacConfigProvider; import com.itsaky.androidide.javac.services.fs.AndroidFsProviderImpl; import com.itsaky.androidide.projects.api.AndroidModule; import com.itsaky.androidide.projects.api.ModuleProject; import com.itsaky.androidide.projects.util.StringSearch; +import com.itsaky.androidide.tooling.api.IProject; import com.itsaky.androidide.utils.ClassTrie; import com.itsaky.androidide.utils.Environment; import com.itsaky.androidide.utils.ILogger; @@ -80,36 +80,29 @@ public class SourceFileManager extends ForwardingJavaFileManager classpaths = configureClasspaths(module); - setLocationLogError(StandardLocation.CLASS_PATH, classpaths); - + setLocationLogError(StandardLocation.CLASS_PATH, configureClasspaths(module)); listLocations(EnumSet.of(StandardLocation.CLASS_PATH, StandardLocation.PLATFORM_CLASS_PATH)); } @NonNull private Set configureClasspaths(final ModuleProject module) { if (module == null) { - setFallbackPlatformClasspath(); - return emptySet(); - } - - final Set classpaths = module.getCompileClasspaths(); - if (!(module instanceof AndroidModule)) { - setFallbackPlatformClasspath(); return emptySet(); } - final AndroidModule androidModule = (AndroidModule) module; - classpaths.addAll(androidModule.getBootClassPaths()); - - setLocationLogError(StandardLocation.PLATFORM_CLASS_PATH, androidModule.getBootClassPaths()); - return classpaths; + if (module instanceof AndroidModule) { + final AndroidModule androidModule = (AndroidModule) module; + setLocationLogError(StandardLocation.PLATFORM_CLASS_PATH, androidModule.getBootClassPaths()); + } + + return module.getCompileClasspaths(); } private static JavacFileManager createDelegateFileManager() { @@ -117,12 +110,6 @@ public class SourceFileManager extends ForwardingJavaFileManager searchPath) { try { fileManager.setLocation(location, searchPath); diff --git a/tests/test-home/.androidide/init/model.jar b/tests/test-home/.androidide/init/model.jar index 470608ace..0ed621675 100644 Binary files a/tests/test-home/.androidide/init/model.jar and b/tests/test-home/.androidide/init/model.jar differ