Created compiler-module for java completion

The compiler module contains classes from android.jar (API 32)
This commit is contained in:
Akash Yadav
2022-01-24 20:07:47 +05:30
parent c102f6a95b
commit b1102fc7ea
14 changed files with 108 additions and 108 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.itsaky.androidide">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Binary file not shown.
Binary file not shown.
@@ -20,6 +20,7 @@
package com.itsaky.androidide;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Rect;
@@ -51,10 +52,14 @@ import androidx.lifecycle.ViewModelProvider;
import androidx.transition.Slide;
import androidx.transition.TransitionManager;
import com.blankj.utilcode.util.ClipboardUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.IntentUtils;
import com.blankj.utilcode.util.KeyboardUtils;
import com.blankj.utilcode.util.ResourceUtils;
import com.blankj.utilcode.util.SizeUtils;
import com.blankj.utilcode.util.ThrowableUtils;
import com.blankj.utilcode.util.ZipUtils;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.navigation.NavigationView;
@@ -80,6 +85,7 @@ import com.itsaky.androidide.interfaces.DiagnosticClickListener;
import com.itsaky.androidide.interfaces.EditorActivityProvider;
import com.itsaky.androidide.lsp.IDELanguageClientImpl;
import com.itsaky.androidide.managers.PreferenceManager;
import com.itsaky.androidide.managers.ToolsManager;
import com.itsaky.androidide.models.DiagnosticGroup;
import com.itsaky.androidide.models.LogLine;
import com.itsaky.androidide.models.SaveResult;
@@ -93,6 +99,7 @@ import com.itsaky.androidide.shell.ShellServer;
import com.itsaky.androidide.tasks.TaskExecutor;
import com.itsaky.androidide.utils.DialogUtils;
import com.itsaky.androidide.utils.EditorBottomSheetBehavior;
import com.itsaky.androidide.utils.Environment;
import com.itsaky.androidide.utils.LSPUtils;
import com.itsaky.androidide.utils.Logger;
import com.itsaky.androidide.utils.RecursiveFileSearcher;
@@ -114,6 +121,7 @@ import com.unnamed.b.atv.model.TreeNode;
import org.jetbrains.annotations.Contract;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
@@ -123,6 +131,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -330,6 +339,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
super.onResume ();
try {
checkForCompilerModule();
dispatchOnResumeToEditors ();
mFileTreeFragment.listProjectFiles ();
} catch (Throwable th) {
@@ -1036,6 +1046,70 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
////////////// PRIVATE APIS /////////////////////
/////////////////////////////////////////////////
@SuppressWarnings ("deprecation")
private void checkForCompilerModule () {
if (!Environment.isCompilerModuleInstalled ()) {
final var pd = ProgressDialog.show (this,
getString(R.string.title_compiler_module_install),
getString(R.string.msg_compiler_module_install),
true,
false);
final CompletableFuture<Boolean> future = CompletableFuture.supplyAsync (() -> {
final var tmpModule = new File (Environment.TMP_DIR, "compiler-module.zip");
if (!ResourceUtils.copyFileFromAssets (
ToolsManager.getCommonAsset ("compiler-module.zip"),
tmpModule.getAbsolutePath ())) {
throw new CompletionException (new RuntimeException ("Unable to copy compiler-module.zip"));
}
try {
ZipUtils.unzipFile (tmpModule, Environment.COMPILER_MODULE);
} catch (Throwable e) {
throw new CompletionException (e);
}
if (!Environment.isCompilerModuleInstalled ()) {
throw new CompletionException (new RuntimeException ("Unknown error"));
}
try {
FileUtils.delete (tmpModule);
} catch (Exception e) {
// ignored
}
return true;
});
future.whenComplete ((result, error) -> {
pd.dismiss ();
if (error != null) {
showCompilerModuleInstallError (error);
return;
}
getApp ().toast (getString(R.string.msg_compiler_module_installed), Toaster.Type.SUCCESS);
});
}
}
private void showCompilerModuleInstallError (Throwable error) {
final var stacktrace = ThrowableUtils.getFullStackTrace (error);
final var builder = DialogUtils.newMaterialDialogBuilder (this);
builder.setTitle (R.string.title_installation_failed);
builder.setMessage (getString(R.string.msg_compiler_module_install_failed, stacktrace));
builder.setCancelable (false);
builder.setPositiveButton (android.R.string.ok, (dialog, which) -> dialog.dismiss ());
builder.setNegativeButton (R.string.copy, (dialog, which) -> {
ClipboardUtils.copyText (stacktrace);
dialog.dismiss ();
});
builder.show ();
}
private void dispatchOnPauseToEditors () {
CompletableFuture.runAsync (() -> {
for (int i = 0; i < mViewModel.getOpenedFileCount (); i++) {
@@ -21,13 +21,10 @@ package com.itsaky.androidide;
import static com.itsaky.androidide.utils.Environment.*;
import android.graphics.Typeface;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import com.blankj.utilcode.util.ClipboardUtils;
@@ -41,7 +38,6 @@ import com.itsaky.androidide.fragments.sheets.ProgressSheet;
import com.itsaky.androidide.managers.PreferenceManager;
import com.itsaky.androidide.models.ConstantsBridge;
import com.itsaky.androidide.utils.BootstrapInstaller;
import com.itsaky.androidide.utils.DialogUtils;
import com.itsaky.androidide.utils.Logger;
import com.itsaky.androidide.utils.TypefaceUtils;
import com.itsaky.androidide.views.virtualkeys.SpecialButton;
@@ -62,10 +58,8 @@ import java.util.Map;
import org.json.JSONException;
import android.os.Bundle;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
public class TerminalActivity extends StudioActivity {
@@ -213,7 +207,7 @@ public class TerminalActivity extends StudioActivity {
}
private TerminalSession createSession (final String workingDirectory) {
final Map<String, String> envs = getEnvironment (true);
final Map<String, String> envs = getEnvironment ();
final String[] env = new String[envs.size ()];
int i = 0;
for (Map.Entry<String, String> entry : envs.entrySet ()) {
+4
View File
@@ -350,5 +350,9 @@
<string name="msg_reading_bootstrap">Reading bootstrap archive…</string>
<string name="msg_bootstrap_installation_error">Bootstrap installation failed with the following exception.</string>
<string name="title_translations">Translations</string>
<string name="title_compiler_module_install">Installing compiler module</string>
<string name="msg_compiler_module_install">Compiler module is being installed, please wait&#8230;</string>
<string name="msg_compiler_module_install_failed">Compiler module installation failed. The error was:\n%s</string>
<string name="msg_compiler_module_installed">Compiler module installed successfully!</string>
</resources>
@@ -116,7 +116,7 @@ public abstract class BaseApplication extends MultiDexApplication {
ShellServer shellServer = new ShellServer(callback,
"sh",
Environment.mkdirIfNotExits(getRootDir()).getAbsolutePath(),
Environment.getEnvironment(true),
Environment.getEnvironment(),
redirectErrors);
shellServer.start();
return shellServer;
@@ -60,7 +60,7 @@ public class ToolsManager {
}
private static void extractGradlePlugin () {
final var repoDir = new File (Environment.HOME, ".androidide");
final var repoDir = new File (Environment.ANDROIDIDE_HOME, "repo");
FileUtils.createOrExistsDir (repoDir);
final var zip = new File (Environment.TMP_DIR, "gradle-plugin.zip");
@@ -118,7 +118,7 @@ public class ToolsManager {
try {
final boolean isOld = LOG_SENDER_VERSION > prefs.getInt(KEY_LOG_SENDER_VERSION, 0);
if(isOld) {
final File logsenderZip = new File(Environment.JLS_HOME, "logsender.zip");
final File logsenderZip = new File(Environment.TMP_DIR, "logsender.zip");
ResourceUtils.copyFileFromAssets(getCommonAsset("logsender.zip"), logsenderZip.getAbsolutePath());
ZipUtils.unzipFile(logsenderZip, Environment.HOME);
prefs.putInt(KEY_LOG_SENDER_VERSION, LOG_SENDER_VERSION);
@@ -17,6 +17,8 @@
**************************************************************************************/
package com.itsaky.androidide.shell;
import com.itsaky.androidide.utils.Environment;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
@@ -78,34 +80,14 @@ public class CommonProcessExecutor implements IProcessExecutor {
}
private static File getHome() {
try {
final Class<?> env = CommonProcessExecutor.class.getClassLoader().loadClass("com.itsaky.androidide.utils.Environment");
final Field home = env.getDeclaredField("HOME");
home.setAccessible(true);
return (File) home.get(null);
} catch (Throwable th) {
// ignored
}
// Return this if we cannot get it from Environment class
return new File("/data/data/com.itsaky.androidide/files/framework");
return Environment.HOME;
}
private static Map<String, String> getEnv() {
try {
final Class<?> env = CommonProcessExecutor.class.getClassLoader().loadClass("com.itsaky.androidide.utils.Environment");
final Method method = env.getDeclaredMethod("getEnvironment", boolean.class);
method.setAccessible(true);
return (Map<String, String>) method.invoke(null, true);
} catch (Throwable th) {
// ignored
}
// Return this if we cannot get it from Environment class
return new HashMap<String, String>();
return Environment.getEnvironment ();
}
private class ExitListenerRunnable implements Runnable {
private static class ExitListenerRunnable implements Runnable {
private final Process proc;
private final IProcessExitListener listener;
@@ -41,9 +41,9 @@ public final class Environment {
public static File ROOT;
public static File SYSROOT;
public static File HOME;
public static File ANDROIDIDE_HOME;
public static File JAVA_HOME;
public static File ANDROID_HOME;
public static File JLS_HOME;
public static File TMP_DIR;
public static File BIN_DIR;
public static File LIB_DIR;
@@ -52,9 +52,15 @@ public final class Environment {
public static File LIB_HOOK;
public static File LIB_HOOK2;
/**
* JDK modules used by the java language server for completions.
* This version of JDK modules contains only the classes included in
* android.jar
*/
public static File COMPILER_MODULE;
public static File INIT_SCRIPT;
public static File PROJECT_DATA_FILE;
public static File JLS_JAR;
public static File GRADLE_PROPS;
public static File GRADLE_USER_HOME;
@@ -82,17 +88,17 @@ public final class Environment {
ROOT = app.getIDEDataDir();
SYSROOT = mkdirIfNotExits(new File(app.getIDEDataDir(), "sysroot"));
HOME = mkdirIfNotExits(app.getRootDir());
JLS_HOME = mkdirIfNotExits(new File(app.getIDEDataDir(), "jls"));
ANDROIDIDE_HOME = mkdirIfNotExits (new File (HOME, ".androidide"));
TMP_DIR = mkdirIfNotExits(new File(SYSROOT, "tmp"));
BIN_DIR = mkdirIfNotExits(new File(SYSROOT, "bin"));
LIB_DIR = mkdirIfNotExits(new File(SYSROOT, "lib"));
PROJECTS_DIR = mkdirIfNotExits(new File(FileUtil.getExternalStorageDir(), PROJECTS_FOLDER));
COMPILER_MODULE = mkdirIfNotExits (new File (ANDROIDIDE_HOME, "compiler-module"));
IDE_PROPS_FILE = new File(SYSROOT, "etc/ide-environment.properties");
LIB_HOOK = new File(LIB_DIR, "libhook.so");
LIB_HOOK2 = new File(LIB_DIR, "libhook2.so");
PROJECT_DATA_FILE = new File(TMP_DIR, "ide_project");
JLS_JAR = new File(JLS_HOME, "jls.jar");
INIT_SCRIPT = new File(mkdirIfNotExits(new File(app.getIDEDataDir(), "init")), "data/common/androidide.init.gradle");
BOOTCLASSPATH = new File("");
@@ -156,7 +162,7 @@ public final class Environment {
BOOTCLASSPATH = new File(file.getAbsolutePath());
}
public static Map<String, String> getEnvironment(boolean publicUse) {
public static Map<String, String> getEnvironment () {
if(!ENV_VARS.isEmpty()) {
return ENV_VARS;
@@ -171,11 +177,6 @@ public final class Environment {
ENV_VARS.put("LANG", "en_US.UTF-8");
ENV_VARS.put("LC_ALL", "en_US.UTF-8");
if(!publicUse) {
// These environment variables are not supposed to be accessed by users
ENV_VARS.put("JLS_HOME", JLS_HOME.getAbsolutePath());
}
ENV_VARS.put("SYSROOT", SYSROOT.getAbsolutePath());
ENV_VARS.put("BUSYBOX", BUSYBOX.getAbsolutePath());
@@ -266,6 +267,13 @@ public final class Environment {
return in;
}
public static boolean isCompilerModuleInstalled () {
final var modules = new File (COMPILER_MODULE, "lib/modules");
final var release = new File (COMPILER_MODULE, "release");
return modules.exists () && modules.isFile ()
&& release.exists () && release.isFile ();
}
private static final List<String> blacklist = new ArrayList<>();
Binary file not shown.
@@ -1,61 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.itsaky.javac11;
import com.itsaky.androidide.utils.Environment;
import java.nio.file.Path;
/**
* Javac classes read some important locations from this class file.
*
* @author Akash Yadav
*/
public class LocationsProvider {
/**
* Path of the JDK installation directory. Use by :
* <br>
* 1. {@link com.sun.tools.javac.file.Locations Locations} <br>
* 2. {@link jdk.internal.jrtfs.SystemImage SystemImage}
*/
public static Path javaHome;
public static Path javaLibDir;
public static Path javaLibModules;
public static void init () {
if (Environment.JAVA_HOME == null)
Environment.init ();
javaHome = Environment.JAVA_HOME.toPath ();
javaLibDir = javaHome.resolve ("lib");
javaLibModules = javaLibDir.resolve ("modules");
}
public static Path getJavaHome () {
return javaHome;
}
public static Path getJavaLibDir () {
return javaLibDir;
}
public static Path getJavaLibModules () {
return javaLibModules;
}
}
@@ -153,7 +153,7 @@ public class CompileBatch implements AutoCloseable {
Collections.addAll (list, "-classpath", joinPath (classPath));
Collections.addAll (list, "-source", "11", "-target", "11");
Collections.addAll (list, "--system", Environment.JAVA_HOME.getAbsolutePath ());
Collections.addAll (list, "--system", Environment.COMPILER_MODULE.getAbsolutePath ());
Collections.addAll (list, "-proc:none");
Collections.addAll (list, "-g");
@@ -25,7 +25,6 @@
package jdk.internal.jrtfs;
import com.itsaky.androidide.utils.Environment;
import com.itsaky.javac11.LocationsProvider;
import java.io.IOException;
import java.nio.file.FileSystem;
@@ -111,6 +110,6 @@ abstract class SystemImage {
* otherwise the JDK home is located relative to jrt-fs.jar.
*/
private static String findHome() {
return Environment.JAVA_HOME.getAbsolutePath ();
return Environment.COMPILER_MODULE.getAbsolutePath ();
}
}