mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
Enhanced working of JLS
Request signature help if corresponding action is available in CompletionItem Fixed invalid insertion of CompletionItem texts Fix android.jar not provided to JLS
This commit is contained in:
Binary file not shown.
@@ -120,6 +120,8 @@ import java.util.regex.Pattern;
|
||||
import me.piruin.quickaction.ActionItem;
|
||||
import me.piruin.quickaction.QuickAction;
|
||||
import com.itsaky.androidide.models.project.IDEProject;
|
||||
import java.util.Optional;
|
||||
import com.itsaky.androidide.models.project.IDEModule;
|
||||
|
||||
public class EditorActivity extends StudioActivity implements FileTreeFragment.FileActionListener,
|
||||
IDEService.BuildListener,
|
||||
@@ -293,7 +295,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
|
||||
}
|
||||
|
||||
private void startServices() {
|
||||
getBuildService().initProject();
|
||||
getBuildService().assembleDebug(false);
|
||||
}
|
||||
|
||||
private void removeFromParent(View v) {
|
||||
@@ -712,7 +714,19 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
|
||||
|
||||
@Override
|
||||
public void onProjectLoaded(IDEProject project) {
|
||||
|
||||
Optional<IDEModule> appModule = project.getModuleByPath(":app");
|
||||
if(appModule.isPresent()) {
|
||||
IDEModule app = appModule.get();
|
||||
setStatus(getString(R.string.msg_starting_completion));
|
||||
mProject.setClassPaths(app.dependencies);
|
||||
|
||||
File androidJar = new File(Environment.ANDROID_HOME, String.format("platforms/%s/android.jar", app.compileSdkVersion));
|
||||
if(androidJar.exists()) {
|
||||
Environment.setBootClasspath(androidJar);
|
||||
mProject.addClasspath(androidJar.getAbsolutePath());
|
||||
createServices();
|
||||
} else setStatus("android.jar not found!");
|
||||
} else setStatus("Cannot get :app module...");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.itsaky.toaster.Toaster;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Callable;
|
||||
import com.itsaky.androidide.models.ConstantsBridge;
|
||||
|
||||
public class MainActivity extends StudioActivity implements View.OnClickListener, ProjectWriterCallback {
|
||||
|
||||
@@ -68,7 +69,7 @@ public class MainActivity extends StudioActivity implements View.OnClickListener
|
||||
|
||||
binding.getRoot().post(() -> {
|
||||
PreferenceManager manager = getApp().getPrefManager();
|
||||
if(manager.wasProjectOpened()) {
|
||||
if(manager.wasProjectOpened() && ConstantsBridge.SPLASH_TO_MAIN) {
|
||||
String path = manager.getOpenedProject();
|
||||
if(path == null && path.trim().isEmpty()) {
|
||||
getApp().toast(R.string.msg_opened_project_does_not_exist, Toaster.Type.INFO);
|
||||
@@ -81,6 +82,8 @@ public class MainActivity extends StudioActivity implements View.OnClickListener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConstantsBridge.SPLASH_TO_MAIN = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,7 @@ import android.view.View;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.itsaky.androidide.app.StudioActivity;
|
||||
import com.itsaky.androidide.databinding.ActivitySplashBinding;
|
||||
import com.itsaky.androidide.fragments.sheets.ProgressSheet;
|
||||
import com.itsaky.androidide.shell.ShellServer;
|
||||
import com.itsaky.androidide.utils.Environment;
|
||||
import java.io.File;
|
||||
import com.itsaky.androidide.models.ConstantsBridge;
|
||||
|
||||
public class SplashActivity extends StudioActivity
|
||||
{
|
||||
@@ -20,8 +17,8 @@ public class SplashActivity extends StudioActivity
|
||||
private final Runnable mRunnable = new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
public void run() {
|
||||
ConstantsBridge.SPLASH_TO_MAIN = true;
|
||||
startActivity(new Intent(SplashActivity.this, MainActivity.class));
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -63,8 +63,7 @@ public class StudioApp extends MultiDexApplication
|
||||
public static final long BUSYBOX_VERSION = 1;
|
||||
public static final String TAG = "StudioApp";
|
||||
public static final String ASSETS_DATA_DIR = "data/";
|
||||
public static final String PROJECTS_FOLDER = "AndroidIDEProjects";
|
||||
|
||||
|
||||
public static final String NOTIFICATION_ID_UPDATE = "17571";
|
||||
public static final String NOTIFICATION_ID_DEVS = "17572";
|
||||
|
||||
@@ -279,7 +278,7 @@ public class StudioApp extends MultiDexApplication
|
||||
}
|
||||
|
||||
public File getProjectsDir() {
|
||||
return Environment.mkdirIfNotExits(new File(FileUtil.getExternalStorageDir(), PROJECTS_FOLDER));
|
||||
return Environment.PROJECTS_DIR;
|
||||
}
|
||||
|
||||
public File[] listProjects() {
|
||||
|
||||
+11
-25
@@ -8,6 +8,7 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.itsaky.androidide.app.StudioApp;
|
||||
import com.itsaky.androidide.models.AndroidProject;
|
||||
import com.itsaky.androidide.shell.ShellServer;
|
||||
@@ -30,8 +31,10 @@ import com.itsaky.lsp.JavaColors;
|
||||
import com.itsaky.lsp.JavaReportProgressParams;
|
||||
import com.itsaky.lsp.JavaStartProgressParams;
|
||||
import com.itsaky.lsp.LanguageClient;
|
||||
import com.itsaky.lsp.Location;
|
||||
import com.itsaky.lsp.Message;
|
||||
import com.itsaky.lsp.PublishDiagnosticsParams;
|
||||
import com.itsaky.lsp.ReferenceParams;
|
||||
import com.itsaky.lsp.SignatureHelp;
|
||||
import com.itsaky.lsp.TextDocumentPositionParams;
|
||||
import com.itsaky.lsp.TextEdit;
|
||||
@@ -48,9 +51,6 @@ import java.util.List;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import com.itsaky.lsp.Location;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.itsaky.lsp.ReferenceParams;
|
||||
|
||||
public class JavaLanguageServer implements ShellServer.Callback {
|
||||
|
||||
@@ -81,14 +81,13 @@ public class JavaLanguageServer implements ShellServer.Callback {
|
||||
"--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED " +
|
||||
"--add-opens jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED " +
|
||||
"-cp $JLS_HOME/lib/jls.jar:$JLS_HOME/lib/gson.jar:$JLS_HOME/lib/protobuf.jar " +
|
||||
"org.javacs.Main";
|
||||
"org.javacs.Main --quiet";
|
||||
|
||||
|
||||
private static final String CONTENT_LENGTH = "Content-Length: ";
|
||||
private static final String SOCKET_HOST = "localhost";
|
||||
private static final int SOCKET_PORT = 5443;
|
||||
private static int UNIVERSION_ID = 1;
|
||||
private static final Logger logger = Logger.instance("JavaLanguageServer");
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
public JavaLanguageServer(AndroidProject project, LanguageClient client) {
|
||||
@@ -114,7 +113,7 @@ public class JavaLanguageServer implements ShellServer.Callback {
|
||||
});
|
||||
}
|
||||
socket.close();
|
||||
logger.i("Socket disconnected");
|
||||
LOG.i("Socket disconnected");
|
||||
} catch (Throwable e) {
|
||||
logEx(e);
|
||||
}
|
||||
@@ -269,7 +268,7 @@ public class JavaLanguageServer implements ShellServer.Callback {
|
||||
send.write(bodyBytes);
|
||||
send.flush();
|
||||
} catch (Throwable e) {
|
||||
logger.e("Error writing to server: " + ThrowableUtils.getFullStackTrace(e));
|
||||
LOG.e("Error writing to server: " + ThrowableUtils.getFullStackTrace(e));
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -286,26 +285,12 @@ public class JavaLanguageServer implements ShellServer.Callback {
|
||||
}
|
||||
|
||||
private void logEx(Throwable th) {
|
||||
logger.e(ThrowableUtils.getFullStackTrace(th));
|
||||
LOG.e(ThrowableUtils.getFullStackTrace(th));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void output(CharSequence charSequence) {
|
||||
// writeOut(charSequence.toString());
|
||||
}
|
||||
|
||||
private BufferedOutputStream os;
|
||||
|
||||
private void writeOut(String data) {
|
||||
try {
|
||||
if(os == null) {
|
||||
os = new BufferedOutputStream(new FileOutputStream(new File(FileUtil.getExternalStorageDir(), "ide_xlog/out.txt"), true));
|
||||
}
|
||||
os.write(data.getBytes());
|
||||
os.flush();
|
||||
} catch (Throwable th) {
|
||||
logger.e(ThrowableUtils.getFullStackTrace(th));
|
||||
}
|
||||
// Nothing is in the output
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,7 +300,6 @@ public class JavaLanguageServer implements ShellServer.Callback {
|
||||
if(line.contains(CONTENT_LENGTH)) line = line.substring(0, line.lastIndexOf(CONTENT_LENGTH));
|
||||
if(this.client == null) return;
|
||||
try {
|
||||
logger.v(line);
|
||||
JsonObject obj = new JsonParser().parse(line.trim()).getAsJsonObject();
|
||||
if(obj.has(Key.METHOD)) {
|
||||
final String method = obj.get(Key.METHOD).getAsString();
|
||||
@@ -369,10 +353,12 @@ public class JavaLanguageServer implements ShellServer.Callback {
|
||||
}
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
logger.e("onServerOut", line, ThrowableUtils.getFullStackTrace(th));
|
||||
LOG.e("onServerOut", line, ThrowableUtils.getFullStackTrace(th));
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger LOG = Logger.instance("JavaLanguageServer");
|
||||
|
||||
public static class Method {
|
||||
public static final String INITIALIZE = "initialize";
|
||||
public static final String INITIALIZED = "initialized";
|
||||
|
||||
@@ -10,8 +10,7 @@ import java.util.Set;
|
||||
public class PreferenceManager {
|
||||
|
||||
private SharedPreferences prefs;
|
||||
private SharedPreferences.Editor editor;
|
||||
|
||||
|
||||
public static final int LOGSENDER_LATEST_VERSION = 102;
|
||||
|
||||
public static final String KEY_FRAMEWORK_DOWNLOADED = "framework_downloaded";
|
||||
@@ -41,11 +40,10 @@ public class PreferenceManager {
|
||||
@SuppressLint("CommitPrefEdits")
|
||||
public PreferenceManager(Context ctx) {
|
||||
this.prefs = androidx.preference.PreferenceManager.getDefaultSharedPreferences(ctx);
|
||||
this.editor = prefs.edit();
|
||||
}
|
||||
|
||||
public PreferenceManager putInt(String key, int val) {
|
||||
editor.putInt(key, val).apply();
|
||||
prefs.edit().putInt(key, val).apply();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -58,7 +56,7 @@ public class PreferenceManager {
|
||||
}
|
||||
|
||||
public PreferenceManager putFloat(String key, float val) {
|
||||
editor.putFloat(key, val).apply();
|
||||
prefs.edit().putFloat(key, val).apply();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -71,7 +69,7 @@ public class PreferenceManager {
|
||||
}
|
||||
|
||||
public PreferenceManager putBoolean(String key, boolean value) {
|
||||
editor.putBoolean(key, value).apply();
|
||||
prefs.edit().putBoolean(key, value).apply();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -84,7 +82,7 @@ public class PreferenceManager {
|
||||
}
|
||||
|
||||
public PreferenceManager putString(String key, String value) {
|
||||
editor.putString(key, value).apply();
|
||||
prefs.edit().putString(key, value).apply();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public class ToolsManager {
|
||||
|
||||
private static PreferenceManager prefs;
|
||||
|
||||
public static final int JLS_VERSION = 1;
|
||||
public static final int JLS_VERSION = 2;
|
||||
public static final int LOGSENDER_VERSION = 1;
|
||||
public static final int CLEANER_VERSION = 1;
|
||||
public static final int GRADLE_API_VERSION = 2;
|
||||
@@ -80,7 +80,7 @@ public class ToolsManager {
|
||||
|
||||
final boolean exists = gson && jls && proto;
|
||||
final boolean isOld = JLS_VERSION > prefs.getInt(KEY_JLS_VERSION, 0);
|
||||
if(!exists || isOld) {
|
||||
if(true/*!exists || isOld*/) {
|
||||
try {
|
||||
extractJls();
|
||||
} catch (Throwable e) {}
|
||||
@@ -114,7 +114,7 @@ public class ToolsManager {
|
||||
|
||||
private static final String BASHRC =
|
||||
"PROMPT_DIRTRIM=2" +
|
||||
"PS1=\'\\[\\e[0;34m\\]\\w\\[\\e[0m\\] \\[\\e[0;97m\\]$\\[\\e[0m\\] \'";
|
||||
"\nPS1=\'\\[\\e[0;34m\\]\\w\\[\\e[0m\\] \\[\\e[0;97m\\]$\\[\\e[0m\\] \'";
|
||||
|
||||
private static final String INIT_SCRIPT =
|
||||
( "import org.gradle.api.Plugin"
|
||||
@@ -174,7 +174,6 @@ public class ToolsManager {
|
||||
+ "\n )"
|
||||
+ "\n {"
|
||||
+ "\n outputs.upToDateWhen { false }"
|
||||
+ "\n dependsOn assembleDebug"
|
||||
+ "\n "
|
||||
+ "\n doLast {"
|
||||
+ "\n def root = project.getRootProject()"
|
||||
@@ -205,16 +204,6 @@ public class ToolsManager {
|
||||
+ "\n project.tasks.getByName(\'assembleDebug\').finalizedBy(\'initializeIDEProject\')"
|
||||
+ "\n project.tasks.getByName(\'assembleRelease\').finalizedBy(\'initializeIDEProject\')"
|
||||
+ "\n }"
|
||||
+ "\n "
|
||||
+ "\n variants.all { variant ->"
|
||||
+ "\n "
|
||||
+ "\n def variantName = variant.name.capitalize()"
|
||||
+ "\n project.tasks.create(name: \"printDependencies${variantName}\", group: \"AndroidIDE\", description: \"List all dependencies in project including those in subprojects for ${variant.name.capitalize()} build.\") {"
|
||||
+ "\n doLast {"
|
||||
+ "\n printDependencies(project, variant)"
|
||||
+ "\n }"
|
||||
+ "\n }"
|
||||
+ "\n }"
|
||||
+ "\n }"
|
||||
+ "\n "
|
||||
+ "\n def addIDEProject (IDEProject parent, Project sub) {"
|
||||
@@ -305,15 +294,6 @@ public class ToolsManager {
|
||||
+ "\n project.tasks.add(task)"
|
||||
+ "\n }"
|
||||
+ "\n }"
|
||||
+ "\n "
|
||||
+ "\n def printDependencies(def project, def variant) {"
|
||||
+ "\n println \">> DEPENDENCIES START <<\""
|
||||
+ "\n variant.getCompileClasspath().each { dep ->"
|
||||
+ "\n println \"{ \\\"file\\\": \\\"${dep.absolutePath}\\\"}\""
|
||||
+ "\n }"
|
||||
+ "\n println \"{ \\\"type\\\":\\\"ANDROID_JAR\\\", \\\"file\\\": \\\"${System.getenv(\'ANDROID_HOME\')}/platforms/${project.android.compileSdkVersion}/android.jar\\\"}\""
|
||||
+ "\n println \">> DEPENDENCIES END <<\""
|
||||
+ "\n }"
|
||||
+ "\n}"
|
||||
+ "\n"
|
||||
+ "\nclass IDEProject {"
|
||||
@@ -321,6 +301,7 @@ public class ToolsManager {
|
||||
+ "\n def displayName = \"Not defined\""
|
||||
+ "\n def description = \"Not defined\""
|
||||
+ "\n def path = \"Not defined\""
|
||||
+ "\n def type = \"ide_project\""
|
||||
+ "\n List<IDEProject> modules = new ArrayList<IDEProject>()"
|
||||
+ "\n List<IDETask> tasks = new ArrayList<IDETask>()"
|
||||
+ "\n List<String> dependencies = new ArrayList<String>()"
|
||||
@@ -334,6 +315,10 @@ public class ToolsManager {
|
||||
+ "\n def versionCode = 0"
|
||||
+ "\n def versionName = \"Not defined\""
|
||||
+ "\n def isLibrary = true"
|
||||
+ "\n "
|
||||
+ "\n public IDEModule () {"
|
||||
+ "\n type = \"ide_module\""
|
||||
+ "\n }"
|
||||
+ "\n}"
|
||||
+ "\n"
|
||||
+ "\nclass IDEAppModule extends IDEModule {"
|
||||
@@ -341,6 +326,7 @@ public class ToolsManager {
|
||||
+ "\n "
|
||||
+ "\n public IDEAppModule() {"
|
||||
+ "\n isLibrary = false"
|
||||
+ "\n type = \"ide_app_module\""
|
||||
+ "\n }"
|
||||
+ "\n}"
|
||||
+ "\n"
|
||||
|
||||
@@ -6,12 +6,16 @@ import com.itsaky.androidide.language.java.server.JavaLanguageServer;
|
||||
import com.itsaky.lsp.CompletionItem;
|
||||
import com.itsaky.lsp.CompletionItemKind;
|
||||
import com.itsaky.lsp.Position;
|
||||
import com.itsaky.lsp.Range;
|
||||
import com.itsaky.lsp.TextDocumentIdentifier;
|
||||
import com.itsaky.lsp.TextDocumentPositionParams;
|
||||
import com.itsaky.lsp.TextEdit;
|
||||
import io.github.rosemoe.editor.text.Content;
|
||||
import io.github.rosemoe.editor.text.Cursor;
|
||||
import io.github.rosemoe.editor.widget.CodeEditor;
|
||||
import java.util.List;
|
||||
import io.github.rosemoe.editor.text.CharPosition;
|
||||
import com.itsaky.androidide.utils.Logger;
|
||||
|
||||
public class CompletionItemWrapper implements SuggestItem, Comparable {
|
||||
|
||||
@@ -57,25 +61,22 @@ public class CompletionItemWrapper implements SuggestItem, Comparable {
|
||||
try {
|
||||
final Cursor cursor = editor.getCursor();
|
||||
if(cursor.isSelected()) return;
|
||||
final int line = cursor.getLeftLine();
|
||||
int col = cursor.getLeftColumn();
|
||||
while(true) {
|
||||
col--;
|
||||
if(col == 0)
|
||||
break;
|
||||
if(!JavaCharacter.isJavaIdentifierPart(editor.getText().charAt(line, col)))
|
||||
break;
|
||||
}
|
||||
col++;
|
||||
Range range = getIdentifierRange(cursor.getLeft(), editor.getText());
|
||||
String text = getInsertText();
|
||||
final boolean shiftLeft = text.contains("$0");
|
||||
final boolean atEnd = text.endsWith("$0");
|
||||
text = text.replace("$0", "");
|
||||
editor.getText().delete(line, col, line, cursor.getLeftColumn());
|
||||
|
||||
editor.getText().delete(range.start.line, range.start.column, range.end.line, range.end.column);
|
||||
cursor.onCommitText(text);
|
||||
|
||||
if(shiftLeft && !atEnd) {
|
||||
editor.moveSelectionLeft();
|
||||
}
|
||||
|
||||
if(item.command != null
|
||||
&& item.command.command != null
|
||||
&& item.command.command.equals(CompletionItem.COMMAND_TRIGGER_PARAMETER_HINTS)) {
|
||||
requestSignature(editor);
|
||||
}
|
||||
|
||||
@@ -97,6 +98,18 @@ public class CompletionItemWrapper implements SuggestItem, Comparable {
|
||||
} catch (Throwable th) {}
|
||||
}
|
||||
|
||||
private Range getIdentifierRange(int end, Content content) {
|
||||
int start = end;
|
||||
while(start > 0 && JavaCharacter.isJavaIdentifierPart(content.charAt(start - 1))) {
|
||||
start--;
|
||||
}
|
||||
|
||||
CharPosition startPos = content.getIndexer().getCharPosition(start);
|
||||
CharPosition endPos = content.getIndexer().getCharPosition(end);
|
||||
Logger.instance("CompletionItemWrapper").d("PartialIdentifer Range: " + start + "," + end + ", text: " + content.subSequence(start, end));
|
||||
return new Range(new Position(startPos.line, startPos.column), new Position(endPos.line, endPos.column));
|
||||
}
|
||||
|
||||
private void requestSignature(CodeEditor editor) {
|
||||
final JavaLanguageServer server = StudioApp.getInstance().getJavaLanguageServer();
|
||||
if (server != null) {
|
||||
@@ -110,6 +123,7 @@ public class CompletionItemWrapper implements SuggestItem, Comparable {
|
||||
@Override
|
||||
public int compareTo(Object p1) {
|
||||
if(p1 instanceof CompletionItemWrapper) {
|
||||
|
||||
CompletionItemWrapper that = (CompletionItemWrapper) p1;
|
||||
return this.getSortText().compareTo(that.getSortText());
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ public class ConstantsBridge {
|
||||
public static boolean EDITORPREF_DRAW_HEX_CHANGED = false;
|
||||
public static boolean CLASS_LOAD_SUCCESS = true;
|
||||
|
||||
public static boolean SPLASH_TO_MAIN = false;
|
||||
|
||||
public static List<String> PROJECT_DEXES = null;
|
||||
|
||||
// Password unzipping the JLS stored in assets
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package com.itsaky.androidide.models.project;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
@@ -13,41 +14,43 @@ public class IDEModule extends IDEProject {
|
||||
* Build tools version of this project
|
||||
*/
|
||||
@SerializedName("buildToolsVersion")
|
||||
int buildToolsVersion = 0;
|
||||
public String buildToolsVersion;
|
||||
|
||||
/**
|
||||
* Compile SDK version of this project
|
||||
*
|
||||
* Representation: 'android-31', 'android-30', 'android-29', etc
|
||||
*/
|
||||
@SerializedName("compileSdkVersion")
|
||||
int compileSdkVersion = 0;
|
||||
public String compileSdkVersion;
|
||||
|
||||
/**
|
||||
* Minimum SDK version of this project
|
||||
*/
|
||||
@SerializedName("minSdk")
|
||||
int minSdk = 0;
|
||||
public SDK minSdk;
|
||||
|
||||
/**
|
||||
* Target SDK version of this project
|
||||
*/
|
||||
@SerializedName("targetSdk")
|
||||
int targetSdk = 0;
|
||||
public SDK targetSdk;
|
||||
|
||||
/**
|
||||
* Version code of this project
|
||||
*/
|
||||
@SerializedName("versionCode")
|
||||
int versionCode = 0;
|
||||
public int versionCode = 0;
|
||||
|
||||
/**
|
||||
* Version name of this project
|
||||
*/
|
||||
@SerializedName("versionName")
|
||||
String versionName = "Not defined";
|
||||
public String versionName = "Not defined";
|
||||
|
||||
/**
|
||||
* Is this project an Android library project?
|
||||
*/
|
||||
@SerializedName("isLibrary")
|
||||
boolean isLibrary = true;
|
||||
public boolean isLibrary = true;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.itsaky.androidide.models.project;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A model that contains data of a project currently opened in AndroidIDE
|
||||
@@ -38,7 +39,7 @@ public class IDEProject {
|
||||
* Subprojects of this project
|
||||
*/
|
||||
@SerializedName("modules")
|
||||
public List<IDEProject> modules = new ArrayList<>();
|
||||
public List<IDEModule> modules = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Tasks included in this project
|
||||
@@ -51,4 +52,41 @@ public class IDEProject {
|
||||
*/
|
||||
@SerializedName("dependencies")
|
||||
public List<String> dependencies = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Get the module by its path
|
||||
*
|
||||
* @param path Path of the module
|
||||
* @return An Optional containing the IDEModule or Optional.empty()
|
||||
*/
|
||||
public Optional<IDEModule> getModuleByPath(String path) {
|
||||
if(modules != null && modules.size() > 0) {
|
||||
for(IDEModule module : modules) {
|
||||
if(module == null) continue;
|
||||
if(module.path.trim().equals(path.trim()))
|
||||
return Optional.of(module);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores information about a SDK. Like,
|
||||
* • Codename
|
||||
* • API string
|
||||
* • API level
|
||||
*/
|
||||
public static class SDK {
|
||||
|
||||
@SerializedName("codename")
|
||||
public String codename;
|
||||
|
||||
|
||||
@SerializedName("apiString")
|
||||
public String apiString;
|
||||
|
||||
@SerializedName("apiLevel")
|
||||
public int apiLevel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.itsaky.androidide.models.project.IDEAppModule;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.blankj.utilcode.util.FileIOUtils;
|
||||
import com.itsaky.androidide.utils.Logger;
|
||||
import com.itsaky.toaster.Toaster;
|
||||
|
||||
public class IDEService implements ShellServer.Callback {
|
||||
|
||||
@@ -41,8 +42,6 @@ public class IDEService implements ShellServer.Callback {
|
||||
private IDEProject mIDEProject;
|
||||
private AndroidProject project;
|
||||
|
||||
private List<String> dependencies;
|
||||
|
||||
private boolean isBuilding = false;
|
||||
private boolean isRunning = false;
|
||||
private boolean recreateShellOnDone = false;
|
||||
@@ -71,9 +70,7 @@ public class IDEService implements ShellServer.Callback {
|
||||
public IDEService(AndroidProject project) {
|
||||
this.app = StudioApp.getInstance();
|
||||
this.project = project;
|
||||
|
||||
this.shell = app.newShell(this);
|
||||
|
||||
this.isRunning = true;
|
||||
}
|
||||
|
||||
@@ -142,15 +139,18 @@ public class IDEService implements ShellServer.Callback {
|
||||
.registerSubtype(IDEModule.class, "ide_module")
|
||||
.registerSubtype(IDEAppModule.class, "ide_app_module");
|
||||
|
||||
IDEProject ideProject = new GsonBuilder()
|
||||
mIDEProject = new GsonBuilder()
|
||||
.registerTypeAdapterFactory(typeAdapter)
|
||||
.create()
|
||||
.fromJson(
|
||||
FileIOUtils.readFile2String(Environment.PROJECT_DATA_FILE),
|
||||
IDEProject.class
|
||||
);
|
||||
if(local != null) local.onProjectLoaded(ideProject);
|
||||
LOG.i("Deserialized project: " + ideProject, (ideProject != null ? String.format("Name: %s\nPath: %s\nTask count: %d\nSubproject count:%s", ideProject.name, ideProject.path, ideProject.tasks.size(), ideProject.modules.size()) : ""));
|
||||
if(local != null) {
|
||||
local.onProjectLoaded(mIDEProject);
|
||||
} else {
|
||||
app.toast(com.itsaky.androidide.R.string.msg_init_project_failed, Toaster.Type.ERROR);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@@ -165,17 +165,6 @@ public class IDEService implements ShellServer.Callback {
|
||||
recreateShellOnDone = false;
|
||||
}
|
||||
|
||||
private JSONObject asObjectOrNull(String line) {
|
||||
try {
|
||||
if(line == null) return null;
|
||||
line = line.trim();
|
||||
if(line.length() <= 0) return null;
|
||||
return new JSONObject(line);
|
||||
} catch (Throwable th) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
// Delete the tmp directory. It is not needed anymore...
|
||||
FileUtils.delete(Environment.TMP_DIR);
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public class InitializeIDEProject extends BaseGradleTask {
|
||||
|
||||
@Override
|
||||
public boolean canOutput() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import android.os.Build;
|
||||
|
||||
public final class Environment {
|
||||
|
||||
@@ -23,7 +24,9 @@ public final class Environment {
|
||||
public static final File TMP_DIR;
|
||||
public static final File BINDIR;
|
||||
public static final File LIBDIR;
|
||||
public static final File PROJECTS_DIR;
|
||||
public static final File IDEPROPS;
|
||||
public static final File LIBHOOK;
|
||||
|
||||
public static final File INIT_SCRIPT;
|
||||
public static final File PROJECT_DATA_FILE;
|
||||
@@ -43,6 +46,7 @@ public final class Environment {
|
||||
public static final String SAMPLE_GRADLE_PROP_CONTENTS = "# Specify global Gradle properties in this file\n# These properties will be applicable for every project you build with Gradle.";
|
||||
public static List<File> AARS = new ArrayList<>();
|
||||
|
||||
public static final String PROJECTS_FOLDER = "AndroidIDEProjects";
|
||||
private static final String DEFAULT_JAVA_HOME = "/data/data/com.itsaky.androidide/files/framework/jdk";
|
||||
private static final String DEFAULT_ANDROID_HOME = "/data/data/com.itsaky.androidide/files/framework/android-sdk";
|
||||
private static final String DEFAULT_GRADLE_HOME = "/data/data/com.itsaky.androidide/files/framework/gradle-7.1.1";
|
||||
@@ -58,8 +62,10 @@ public final class Environment {
|
||||
TMP_DIR = mkdirIfNotExits(new File(SYSROOT, "tmp"));
|
||||
BINDIR = mkdirIfNotExits(new File(SYSROOT, "bin"));
|
||||
LIBDIR = mkdirIfNotExits(new File(SYSROOT, "lib"));
|
||||
PROJECTS_DIR = mkdirIfNotExits(new File(FileUtil.getExternalStorageDir(), PROJECTS_FOLDER));
|
||||
|
||||
IDEPROPS = new File(SYSROOT, "etc/ide-environment.properties");
|
||||
LIBHOOK = new File(LIBDIR, "libhook.so");
|
||||
PROJECT_DATA_FILE = new File(TMP_DIR, "ide_project");
|
||||
|
||||
INIT_SCRIPT = new File(mkdirIfNotExits(new File(app.getIDEDataDir(), "init")), "androidide.init.gradle");
|
||||
@@ -108,6 +114,7 @@ public final class Environment {
|
||||
map.put("HOME", HOME.getAbsolutePath());
|
||||
map.put("GRADLE_USER_HOME", GRADLE_USER_HOME.getAbsolutePath());
|
||||
map.put("TMPDIR", TMP_DIR.getAbsolutePath());
|
||||
map.put("PROJECT_DIR", PROJECTS_DIR.getAbsolutePath());
|
||||
map.put("ANDROID_DATA", "/data");
|
||||
map.put("ANDROID_ROOT", "/system");
|
||||
map.put("LANG", "en_US.UTF-8");
|
||||
@@ -126,7 +133,7 @@ public final class Environment {
|
||||
map.put("COLORTERM", "truecolor");
|
||||
|
||||
map.put("ANDROID_HOME", ANDROID_HOME.getAbsolutePath());
|
||||
map.put("GRADLE_INSTALLATION_DIR", GRADLE_HOME.getAbsolutePath());
|
||||
map.put("GRADLE_HOME", GRADLE_HOME.getAbsolutePath());
|
||||
map.put("JAVA_HOME", JAVA_HOME.getAbsolutePath());
|
||||
|
||||
/**
|
||||
@@ -139,6 +146,10 @@ public final class Environment {
|
||||
else ld = LIBDIR.getAbsolutePath() + File.pathSeparator + ld;
|
||||
map.put("LD_LIBRARY_PATH", ld);
|
||||
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
map.put("LD_PRELOAD", LIBHOOK.getAbsolutePath());
|
||||
}
|
||||
|
||||
addToEnvIfPresent(map, "ANDROID_ART_ROOT");
|
||||
addToEnvIfPresent(map, "DEX2OATBOOTCLASSPATH");
|
||||
addToEnvIfPresent(map, "ANDROID_I18N_ROOT");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="msg_init_project_failed">Failed to initialize project!</string>
|
||||
<string name="btn_terminal">Terminal</string>
|
||||
<string name="msg_shell_verbose">Verbose output is enabled!</string>
|
||||
<string name="msg_shell_output">Shell output</string>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
<manifest package="com.termux.terminal">
|
||||
<manifest package="com.itsaky.terminal">
|
||||
</manifest>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1200m
|
||||
org.gradle.jvmargs=-Xmx700m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
|
||||
@@ -49,4 +49,6 @@ public class CompletionItem {
|
||||
|
||||
@SerializedName("data")
|
||||
public JsonElement data;
|
||||
|
||||
public static final String COMMAND_TRIGGER_PARAMETER_HINTS = "editor.action.triggerParameterHints";
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ public class CompletionList {
|
||||
|
||||
@SerializedName("items")
|
||||
public List<CompletionItem> items;
|
||||
|
||||
|
||||
public CompletionList() {
|
||||
this.items = new ArrayList<>();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user