diff --git a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JCReusableCompiler.kt b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JCReusableCompiler.kt new file mode 100644 index 000000000..ca821b9cc --- /dev/null +++ b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JCReusableCompiler.kt @@ -0,0 +1,36 @@ +/* + * This file is part of AndroidIDE. + * + * AndroidIDE is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.lsp.java.compiler + +import com.itsaky.androidide.javac.services.compiler.ReusableCompiler +import com.itsaky.androidide.javac.services.compiler.ReusableContext + +/** + * Implementation of the [ReusableCompiler] which replaces necessary components from the + * [ReusableContext]. + * + * @author Akash Yadav + */ +class JCReusableCompiler : ReusableCompiler() { + + override fun onCreateContext(): ReusableContext { + return super.onCreateContext().also { + JavaCompilerImpl.preRegister(context = it, replace = true) + } + } +} diff --git a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JavaCompilerImpl.kt b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JavaCompilerImpl.kt new file mode 100644 index 000000000..d1dc4b83f --- /dev/null +++ b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JavaCompilerImpl.kt @@ -0,0 +1,42 @@ +/* + * This file is part of AndroidIDE. + * + * AndroidIDE is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.lsp.java.compiler + +import com.itsaky.androidide.javac.services.compiler.ReusableContext +import com.itsaky.androidide.javac.services.compiler.ReusableJavaCompiler +import jdkx.tools.JavaFileObject +import openjdk.tools.javac.tree.JCTree.JCCompilationUnit +import openjdk.tools.javac.util.Context + +class JavaCompilerImpl(context: Context?) : ReusableJavaCompiler(context) { + + override fun parse(filename: JavaFileObject?, content: CharSequence?): JCCompilationUnit { + // TODO Prune unnecessary methods to speed up compilation + return super.parse(filename, content) + } + + companion object { + @JvmStatic + fun preRegister(context: ReusableContext, replace: Boolean = false) { + if (replace) { + context.drop(compilerKey) + } + context.put(compilerKey, Context.Factory { JavaCompilerImpl(it) }) + } + } +} diff --git a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JavaCompilerService.java b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JavaCompilerService.java index bc2776242..114cd8be7 100644 --- a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JavaCompilerService.java +++ b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/compiler/JavaCompilerService.java @@ -86,7 +86,7 @@ public class JavaCompilerService implements CompilerProvider { protected final SynchronizedTask synchronizedTask = new SynchronizedTask(); protected final SourceFileManager fileManager; protected final ModuleProject module; - public ReusableCompiler compiler = new ReusableCompiler(); + public ReusableCompiler compiler = new JCReusableCompiler(); protected Set bootClasspathClasses = BootClasspathProvider.getTopLevelClasses( Collections.singleton(Environment.ANDROID_JAR.getAbsolutePath())); diff --git a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/providers/CompletionProvider.java b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/providers/CompletionProvider.java index 6c48a2d14..9846deccf 100644 --- a/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/providers/CompletionProvider.java +++ b/lsp/java/src/main/java/com/itsaky/androidide/lsp/java/providers/CompletionProvider.java @@ -156,7 +156,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp final var sourceObject = new SourceFileObject(file); final var contentBuilder = new StringBuilder(sourceObject.getCharContent(true)); - if (!VMUtils.isJvm()) { + if (false && !VMUtils.isJvm()) { // Cannot use tree sitter in tests // TODO(itsaky): Should we use the legacy method pruner for tests? final StopWatch watch = new StopWatch("Prune method bodies"); diff --git a/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/NBParserFactory.java b/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/NBParserFactory.java index 747909708..004c14ada 100644 --- a/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/NBParserFactory.java +++ b/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/NBParserFactory.java @@ -59,9 +59,9 @@ import openjdk.tools.javac.util.Position; */ public class NBParserFactory extends ParserFactory { - private final ScannerFactory scannerFactory; - private final Names names; - private final CancelService cancelService; + protected final ScannerFactory scannerFactory; + protected final Names names; + protected final CancelService cancelService; public static void preRegister(Context context) { context.put(parserFactoryKey, (Context.Factory) NBParserFactory::new); diff --git a/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/compiler/ReusableContext.kt b/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/compiler/ReusableContext.kt index 6be568e41..e41c50f5a 100644 --- a/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/compiler/ReusableContext.kt +++ b/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/compiler/ReusableContext.kt @@ -31,6 +31,10 @@ import com.itsaky.androidide.javac.services.fs.CacheFSInfoSingleton import com.itsaky.androidide.javac.services.fs.JarPackageProviderImpl import com.itsaky.androidide.utils.VMUtils import com.itsaky.androidide.zipfs2.JarPackageProvider +import java.net.URI +import jdkx.tools.DiagnosticListener +import jdkx.tools.JavaFileManager +import jdkx.tools.JavaFileObject import openjdk.source.util.JavacTask import openjdk.source.util.TaskEvent import openjdk.source.util.TaskEvent.Kind.ANALYZE @@ -53,35 +57,41 @@ import openjdk.tools.javac.util.Context import openjdk.tools.javac.util.DefinedBy import openjdk.tools.javac.util.DefinedBy.Api.COMPILER_TREE import openjdk.tools.javac.util.Log -import java.io.PrintWriter -import java.net.URI -import jdkx.tools.DiagnosticListener -import jdkx.tools.JavaFileManager -import jdkx.tools.JavaFileObject /** * Reusable [Context] for [ReusableCompiler]. + * * @author Akash Yadav */ class ReusableContext(cancelService: CancelService) : Context(), TaskListener { - + private val flowCompleted = mutableSetOf() - + init { put(Log.logKey, ReusableLog.factory) put(FSInfo::class.java, if (VMUtils.isJvm()) CacheFSInfo() else CacheFSInfoSingleton) put(JavaCompiler.compilerKey, ReusableJavaCompiler.factory) put(JavacFlowListener.flowListenerKey, JavacFlowListener { this.hasFlowCompleted(it) }) put(JarPackageProvider::class.java, JarPackageProviderImpl) - registerNBServices(cancelService) + + NBAttr.preRegister(this) + NBParserFactory.preRegister(this) + NBTreeMaker.preRegister(this) + NBJavacTrees.preRegister(this) + NBResolve.preRegister(this) + NBEnter.preRegister(this) + NBMemberEnter.preRegister(this, false) + NBClassFinder.preRegister(this) + NBClassReader.preRegister(this) + CancelService.preRegister(this, cancelService) } - + @DefinedBy(COMPILER_TREE) override fun started(e: TaskEvent) { // log.debug("Started: $e") // Do nothing } - + @DefinedBy(COMPILER_TREE) override fun finished(e: TaskEvent) { if (e.kind == ANALYZE) { @@ -91,7 +101,7 @@ class ReusableContext(cancelService: CancelService) : Context(), TaskListener { } } } - + fun clear() { drop(Arguments.argsKey) drop(DiagnosticListener::class.java) @@ -101,7 +111,7 @@ class ReusableContext(cancelService: CancelService) : Context(), TaskListener { drop(JavacTask::class.java) drop(JavacTrees::class.java) drop(JavacElements::class.java) - + if (ht[Log.logKey] is ReusableLog) { // log already init-ed - not first round (Log.instance(this) as ReusableLog).clear() @@ -115,15 +125,17 @@ class ReusableContext(cancelService: CancelService) : Context(), TaskListener { MultiTaskListener.instance(this).clear() } } - - private fun drop(k: Key?) { + + /** **FOR INTERNAL USE ONLY!** */ + fun drop(k: Key?) { ht.remove(k) } - - private fun drop(c: Class?) { - ht.remove(key(c)) + + /** **FOR INTERNAL USE ONLY!** */ + fun drop(c: Class?) { + drop(key(c)) } - + private fun hasFlowCompleted(fo: JavaFileObject?): Boolean { return if (fo == null) { false @@ -135,17 +147,4 @@ class ReusableContext(cancelService: CancelService) : Context(), TaskListener { } } } - - private fun registerNBServices(cancelService: CancelService) { - NBAttr.preRegister(this) - NBParserFactory.preRegister(this) - NBTreeMaker.preRegister(this) - NBJavacTrees.preRegister(this) - NBResolve.preRegister(this) - NBEnter.preRegister(this) - NBMemberEnter.preRegister(this, false) - NBClassFinder.preRegister(this) - NBClassReader.preRegister(this) - CancelService.preRegister(this, cancelService) - } } diff --git a/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/compiler/ReusableJavaCompiler.kt b/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/compiler/ReusableJavaCompiler.kt index 9dd5fad08..f5e1c44d4 100644 --- a/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/compiler/ReusableJavaCompiler.kt +++ b/subprojects/javac-services/src/main/java/com/itsaky/androidide/javac/services/compiler/ReusableJavaCompiler.kt @@ -25,7 +25,7 @@ import openjdk.tools.javac.util.Context * Reusable JavaCompiler; exposes a method to clean up the component from leftovers associated * with previous compilations. */ -internal class ReusableJavaCompiler(context: Context?) : NBJavaCompiler(context) { +open class ReusableJavaCompiler(context: Context?) : NBJavaCompiler(context) { companion object { val factory = Context.Factory { ReusableJavaCompiler(it) }