mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
fix(projects): introduce workspace API and remove 'Project' model
This commit is contained in:
@@ -60,8 +60,8 @@ import com.itsaky.androidide.lsp.util.LSPEditorActions
|
||||
import com.itsaky.androidide.models.Range
|
||||
import com.itsaky.androidide.projects.FileManager.getActiveDocumentCount
|
||||
import com.itsaky.androidide.projects.IProjectManager.Companion.getInstance
|
||||
import com.itsaky.androidide.projects.IWorkspace
|
||||
import com.itsaky.androidide.projects.ModuleProject
|
||||
import com.itsaky.androidide.projects.Project
|
||||
import com.itsaky.androidide.utils.DocumentUtils
|
||||
import com.itsaky.androidide.utils.VMUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -131,10 +131,10 @@ class JavaLanguageServer : ILanguageServer {
|
||||
this._settings = settings
|
||||
}
|
||||
|
||||
override fun setupWithProject(project: Project) {
|
||||
override fun setupWorkspace(workspace: IWorkspace) {
|
||||
LSPEditorActions.ensureActionsMenuRegistered(JavaCodeActionsMenu)
|
||||
|
||||
// Once we have project initialized
|
||||
// Once we have workspace initialized
|
||||
// Destory the NO_MODULE_COMPILER instance
|
||||
JavaCompilerService.NO_MODULE_COMPILER.destroy()
|
||||
|
||||
@@ -144,15 +144,15 @@ class JavaLanguageServer : ILanguageServer {
|
||||
// Clear cached JAR file system for R.jar
|
||||
// Using the cached instance will result in completions not being updated for updated resources
|
||||
// TODO Clearing caches for JAR files ending with '/R.jar' is probably not a good idea
|
||||
// Maybe this could be improved by using data from the AndroidModule project model
|
||||
// Maybe this could be improved by using data from the AndroidModule workspace model
|
||||
clearCachesForPaths { path: String -> path.endsWith("/R.jar") }
|
||||
|
||||
// Clear cached module-specific compilers
|
||||
JavaCompilerProvider.getInstance().destroy()
|
||||
|
||||
// Cache classpath locations
|
||||
for (subModule in project.subProjects) {
|
||||
if (subModule !is ModuleProject || subModule.path == project.rootProject.path) {
|
||||
for (subModule in workspace.getSubProjects()) {
|
||||
if (subModule !is ModuleProject || subModule.path == workspace.getRootProject().path) {
|
||||
continue
|
||||
}
|
||||
SourceFileManager.forModule(subModule)
|
||||
@@ -173,7 +173,8 @@ class JavaLanguageServer : ILanguageServer {
|
||||
}
|
||||
|
||||
completionProvider.reset(
|
||||
compiler, settings, cachedCompletion) { cachedCompletion: CachedCompletion ->
|
||||
compiler, settings, cachedCompletion
|
||||
) { cachedCompletion: CachedCompletion ->
|
||||
updateCachedCompletion(cachedCompletion)
|
||||
}
|
||||
|
||||
@@ -239,9 +240,9 @@ class JavaLanguageServer : ILanguageServer {
|
||||
if (!DocumentUtils.isJavaFile(file)) {
|
||||
return JavaCompilerService.NO_MODULE_COMPILER
|
||||
}
|
||||
val root = getInstance().rootProject
|
||||
val workspace = getInstance().getWorkspace()
|
||||
?: return JavaCompilerService.NO_MODULE_COMPILER
|
||||
val module = root.findModuleForFile(file!!) ?: return JavaCompilerService.NO_MODULE_COMPILER
|
||||
val module = workspace.findModuleForFile(file!!) ?: return JavaCompilerService.NO_MODULE_COMPILER
|
||||
return JavaCompilerProvider.get(module)
|
||||
}
|
||||
|
||||
@@ -271,7 +272,7 @@ class JavaLanguageServer : ILanguageServer {
|
||||
// TODO Find an alternative to efficiently update changeDelta in JavaCompilerService instance
|
||||
JavaCompilerService.NO_MODULE_COMPILER.onDocumentChange(event)
|
||||
val module = getInstance()
|
||||
.findModuleForFile(event.changedFile)
|
||||
.getWorkspace()?.findModuleForFile(event.changedFile, true)
|
||||
if (module != null) {
|
||||
val compiler = JavaCompilerProvider.get(module)
|
||||
compiler.onDocumentChange(event)
|
||||
|
||||
@@ -105,7 +105,8 @@ abstract class BaseJavaCodeAction : EditorActionItem {
|
||||
}
|
||||
|
||||
protected fun ActionData.requireCompiler(): JavaCompilerService {
|
||||
val module = IProjectManager.getInstance().findModuleForFile(requireFile(), false)
|
||||
val module =
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(requireFile(), false)
|
||||
requireNotNull(module) {
|
||||
"Cannot get compiler instance. Unable to find module for file: ${requireFile().name}"
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ abstract class FieldBasedAction : BaseJavaCodeAction() {
|
||||
com.itsaky.androidide.models.Range::class.java,
|
||||
CodeEditor::class.java
|
||||
) ||
|
||||
IProjectManager.getInstance().rootProject == null
|
||||
IProjectManager.getInstance().getWorkspace() == null
|
||||
) {
|
||||
markInvisible()
|
||||
return
|
||||
@@ -73,7 +73,8 @@ abstract class FieldBasedAction : BaseJavaCodeAction() {
|
||||
override suspend fun execAction(data: ActionData): Any {
|
||||
val range = data[com.itsaky.androidide.models.Range::class.java]!!
|
||||
val file = data.requirePath()
|
||||
val module = IProjectManager.getInstance().findModuleForFile(file, false) ?: return Any()
|
||||
val module =
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(file, false) ?: return Any()
|
||||
|
||||
return JavaCompilerProvider.get(module).compile(file).get { task ->
|
||||
val triple = findFields(task, file, range)
|
||||
|
||||
+3
-3
@@ -67,7 +67,7 @@ class AddImportAction : BaseJavaCodeAction() {
|
||||
|
||||
val file = data.requireFile()
|
||||
val module =
|
||||
IProjectManager.getInstance().findModuleForFile(file, false)
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(file, false)
|
||||
?: run {
|
||||
markInvisible()
|
||||
return
|
||||
@@ -99,7 +99,7 @@ class AddImportAction : BaseJavaCodeAction() {
|
||||
)!!
|
||||
val file = data.requireFile()
|
||||
val module =
|
||||
IProjectManager.getInstance().findModuleForFile(file, false)
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(file, false)
|
||||
?: run {
|
||||
markInvisible()
|
||||
return Any()
|
||||
@@ -140,7 +140,7 @@ class AddImportAction : BaseJavaCodeAction() {
|
||||
|
||||
val file = data.requireFile()
|
||||
val module =
|
||||
IProjectManager.getInstance().findModuleForFile(file, false)
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(file, false)
|
||||
?: run {
|
||||
markInvisible()
|
||||
return
|
||||
|
||||
+3
-1
@@ -64,7 +64,9 @@ class AddThrowsAction : BaseJavaCodeAction() {
|
||||
val diagnostic = data[DiagnosticItem::class.java]!!
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val file = data.requirePath()
|
||||
return compiler.compile(file).get { task ->
|
||||
val needsThrow = CodeActionUtils.findMethod(task, diagnostic.range)
|
||||
|
||||
+3
-1
@@ -66,7 +66,9 @@ class CreateMissingMethodAction : BaseJavaCodeAction() {
|
||||
val diagnostic = data[com.itsaky.androidide.lsp.models.DiagnosticItem::class.java]!!
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val file = data.requirePath()
|
||||
return compiler.compile(file).get {
|
||||
CreateMissingMethod(file, findPosition(it, diagnostic.range.start))
|
||||
|
||||
+3
-1
@@ -67,7 +67,9 @@ class FieldToBlockAction : BaseJavaCodeAction() {
|
||||
override suspend fun execAction(data: ActionData): Any {
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val diagnostic = data[DiagnosticItem::class.java]!!
|
||||
val file = data.requirePath()
|
||||
|
||||
|
||||
+3
-1
@@ -65,7 +65,9 @@ class RemoveClassAction : BaseJavaCodeAction() {
|
||||
val diagnostic = data[com.itsaky.androidide.lsp.models.DiagnosticItem::class.java]!!
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val file = data.requirePath()
|
||||
|
||||
return compiler.compile(file).get {
|
||||
|
||||
+3
-1
@@ -65,7 +65,9 @@ class RemoveMethodAction : BaseJavaCodeAction() {
|
||||
val diagnostic = data[com.itsaky.androidide.lsp.models.DiagnosticItem::class.java]!!
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val file = data.requirePath()
|
||||
|
||||
return compiler.compile(file).get {
|
||||
|
||||
+3
-1
@@ -66,7 +66,9 @@ class RemoveUnusedThrowsAction : BaseJavaCodeAction() {
|
||||
val d = data[com.itsaky.androidide.lsp.models.DiagnosticItem::class.java]!!
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val file = data.requirePath()
|
||||
return compiler.compile(file).get { task ->
|
||||
val notThrown = CodeActionUtils.extractNotThrownExceptionName(d.message)
|
||||
|
||||
+3
-1
@@ -65,7 +65,9 @@ class SuppressUncheckedWarningAction : BaseJavaCodeAction() {
|
||||
val diagnostic = data[com.itsaky.androidide.lsp.models.DiagnosticItem::class.java]!!
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val file = data.requirePath()
|
||||
return compiler.compile(file).get { task ->
|
||||
val warnedMethod = CodeActionUtils.findMethod(task, diagnostic.range)
|
||||
|
||||
+3
-1
@@ -70,7 +70,9 @@ class VariableToStatementAction : BaseJavaCodeAction() {
|
||||
val diagnostic = data[com.itsaky.androidide.lsp.models.DiagnosticItem::class.java]!!
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val path = data.requirePath()
|
||||
|
||||
return compiler.compile(path).get {
|
||||
|
||||
+3
-1
@@ -82,7 +82,9 @@ class GenerateConstructorAction : FieldBasedAction() {
|
||||
private fun generateConstructor(data: ActionData, selected: MutableSet<String>) {
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return)
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return
|
||||
)
|
||||
val range = data[com.itsaky.androidide.models.Range::class.java]!!
|
||||
val file = data.requirePath()
|
||||
|
||||
|
||||
+3
-1
@@ -65,7 +65,9 @@ class GenerateMissingConstructorAction : BaseJavaCodeAction() {
|
||||
val diagnostic = data[com.itsaky.androidide.lsp.models.DiagnosticItem::class.java]!!
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val file = data.requirePath()
|
||||
return compiler.compile(file).get { task ->
|
||||
val needsConstructor =
|
||||
|
||||
+3
-1
@@ -89,7 +89,9 @@ class GenerateSettersAndGettersAction : FieldBasedAction() {
|
||||
private fun generateForFields(data: ActionData, names: MutableSet<String>) {
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return)
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return
|
||||
)
|
||||
val range = data[com.itsaky.androidide.models.Range::class.java]!!
|
||||
val file = data.requirePath()
|
||||
|
||||
|
||||
+3
-1
@@ -84,7 +84,9 @@ class GenerateToStringMethodAction : FieldBasedAction() {
|
||||
private fun generateToString(data: ActionData, selected: MutableSet<String>) {
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return)
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return
|
||||
)
|
||||
val range = data[com.itsaky.androidide.models.Range::class.java]!!
|
||||
val file = data.requirePath()
|
||||
|
||||
|
||||
+9
-3
@@ -95,7 +95,9 @@ class OverrideSuperclassMethodsAction : BaseJavaCodeAction() {
|
||||
val range = data[com.itsaky.androidide.models.Range::class.java]!!
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return Any())
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return Any()
|
||||
)
|
||||
val file = data.requirePath()
|
||||
|
||||
return compiler.compile(file).get { task ->
|
||||
@@ -203,7 +205,9 @@ class OverrideSuperclassMethodsAction : BaseJavaCodeAction() {
|
||||
private fun overrideMethods(data: ActionData, checkedMethods: MutableList<MethodPtr>) {
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return)
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return
|
||||
)
|
||||
val file = data.requirePath()
|
||||
|
||||
compiler.compile(file).run { task ->
|
||||
@@ -270,7 +274,9 @@ class OverrideSuperclassMethodsAction : BaseJavaCodeAction() {
|
||||
) {
|
||||
val compiler =
|
||||
JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(data.requireFile(), false) ?: return)
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(data.requireFile(), false)
|
||||
?: return
|
||||
)
|
||||
val editor = data[CodeEditor::class.java]!!
|
||||
val file = data.requirePath()
|
||||
val text = editor.text
|
||||
|
||||
+2
-1
@@ -41,7 +41,8 @@ abstract class AdvancedJavaEditHandler(protected val file: Path) : BaseJavaEditH
|
||||
index: Int
|
||||
) {
|
||||
val compiler = JavaCompilerProvider.get(
|
||||
IProjectManager.getInstance().findModuleForFile(file, false) ?: return)
|
||||
IProjectManager.getInstance().getWorkspace()?.findModuleForFile(file, false) ?: return
|
||||
)
|
||||
performEdits(compiler, editor, item)
|
||||
|
||||
executeCommand(editor, item.command)
|
||||
|
||||
+3
-3
@@ -19,7 +19,7 @@ package com.itsaky.androidide.lsp.java.indexing.internal
|
||||
|
||||
import com.google.auto.service.AutoService
|
||||
import com.itsaky.androidide.indexing.IIndexService
|
||||
import com.itsaky.androidide.projects.Project
|
||||
import com.itsaky.androidide.projects.IWorkspace
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@@ -31,12 +31,12 @@ internal class JavaIndexServiceImpl : IIndexService {
|
||||
override val displayName: String
|
||||
get() = "Java LSP Indexing Service"
|
||||
|
||||
override fun scanFiles(project: Project): Collection<File> {
|
||||
override fun scanFiles(workspace: IWorkspace): Collection<File> {
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
override suspend fun indexFiles(
|
||||
project: Project,
|
||||
workspace: IWorkspace,
|
||||
files: Collection<File>
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -23,12 +23,17 @@ import com.itsaky.androidide.models.Position;
|
||||
import com.itsaky.androidide.models.Range;
|
||||
import com.itsaky.androidide.projects.IProjectManager;
|
||||
import com.itsaky.androidide.projects.ModuleProject;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import jdkx.tools.JavaCompiler;
|
||||
import jdkx.tools.JavaFileObject;
|
||||
import openjdk.source.tree.ClassTree;
|
||||
@@ -42,8 +47,6 @@ import openjdk.source.util.SourcePositions;
|
||||
import openjdk.source.util.TreePath;
|
||||
import openjdk.source.util.Trees;
|
||||
import openjdk.tools.javac.api.JavacTool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Parser {
|
||||
|
||||
@@ -78,20 +81,23 @@ public class Parser {
|
||||
* Create a task that compiles a single file
|
||||
*/
|
||||
private static JavacTask singleFileTask(JavaFileObject file) {
|
||||
final ModuleProject module = IProjectManager.getInstance()
|
||||
.findModuleForFile(Paths.get(file.toUri()));
|
||||
final var workspace = IProjectManager.getInstance().getWorkspace();
|
||||
final var module = workspace != null
|
||||
? workspace.findModuleForFile(Paths.get(file.toUri()), false)
|
||||
: null;
|
||||
|
||||
if (module != null) {
|
||||
FILE_MANAGER = SourceFileManager.forModule(module);
|
||||
}
|
||||
|
||||
return (JavacTask)
|
||||
COMPILER.getTask(
|
||||
null,
|
||||
FILE_MANAGER,
|
||||
Parser::ignoreError,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Collections.singletonList(file));
|
||||
COMPILER.getTask(
|
||||
null,
|
||||
FILE_MANAGER,
|
||||
Parser::ignoreError,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Collections.singletonList(file));
|
||||
}
|
||||
|
||||
private static void ignoreError(jdkx.tools.Diagnostic<? extends JavaFileObject> __) {
|
||||
@@ -215,7 +221,7 @@ public class Parser {
|
||||
int endCol = (int) lines.getColumnNumber(end);
|
||||
|
||||
return new Range(
|
||||
new Position(startLine - 1, startCol - 1), new Position(endLine - 1, endCol - 1));
|
||||
new Position(startLine - 1, startCol - 1), new Position(endLine - 1, endCol - 1));
|
||||
}
|
||||
|
||||
private static int indexOf(CharSequence contents, String name, int start) {
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ class JavaDiagnosticProvider {
|
||||
|
||||
fun analyze(file: Path): DiagnosticResult {
|
||||
|
||||
val module = IProjectManager.getInstance().findModuleForFile(file, false)
|
||||
val module = IProjectManager.getInstance().getWorkspace()?.findModuleForFile(file, false)
|
||||
?: return DiagnosticResult.NO_UPDATE
|
||||
val compiler = JavaCompilerService(module)
|
||||
|
||||
|
||||
@@ -39,12 +39,12 @@ class JavaCompilerProviderTest {
|
||||
|
||||
@Test
|
||||
fun `test module specific compilers`() {
|
||||
val rootProject = IProjectManager.getInstance().rootProject!!
|
||||
val appModule = rootProject.findByPath(":app")!! as ModuleProject
|
||||
val androidLib = rootProject.findByPath(":android-library")!! as ModuleProject
|
||||
val anotherAndroidLib = rootProject.findByPath(":another-android-library")!! as ModuleProject
|
||||
val javaLib = rootProject.findByPath(":java-library")!! as ModuleProject
|
||||
val anotherJavaLib = rootProject.findByPath(":another-java-library")!! as ModuleProject
|
||||
val workspace = IProjectManager.getInstance().getWorkspace()!!
|
||||
val appModule = workspace.getProject(":app") as ModuleProject
|
||||
val androidLib = workspace.getProject(":android-library") as ModuleProject
|
||||
val anotherAndroidLib = workspace.getProject(":another-android-library") as ModuleProject
|
||||
val javaLib = workspace.getProject(":java-library") as ModuleProject
|
||||
val anotherJavaLib = workspace.getProject(":another-java-library") as ModuleProject
|
||||
|
||||
val compilers = mutableSetOf<JavaCompilerService>()
|
||||
for (module in listOf(appModule, androidLib, anotherAndroidLib, javaLib, anotherJavaLib)) {
|
||||
|
||||
Reference in New Issue
Block a user