- Added signature help

This commit is contained in:
itsaky
2021-08-06 09:23:49 +05:30
parent 929258284d
commit f99d51ca42
111 changed files with 1314 additions and 432 deletions
Binary file not shown.
-3
View File
@@ -17,9 +17,6 @@
-dontwarn androidx.lifecycle.**
-keep class androidx.arch.** { *; }
-keep class androidx.lifecycle.** { *; }
-keep class com.itsaky.lsp.** { *; }
-keep class org.eclipse.jdt.** { <init>(...); }
-keep class org.eclipse.jdt.** { static *; }
-keepclasseswithmembernames,includedescriptorclasses class * { native <methods>; }
-keep public class * implements com.bumptech.glide.module.GlideModule
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -6,7 +6,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -26,6 +32,7 @@ import com.blankj.utilcode.util.FileIOUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.IntentUtils;
import com.blankj.utilcode.util.KeyboardUtils;
import com.blankj.utilcode.util.SizeUtils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.tabs.TabLayout;
@@ -56,6 +63,7 @@ import com.itsaky.androidide.models.SheetOption;
import com.itsaky.androidide.receivers.LogReceiver;
import com.itsaky.androidide.services.IDEService;
import com.itsaky.androidide.shell.ShellServer;
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE;
import com.itsaky.androidide.tasks.GradleTask;
import com.itsaky.androidide.tasks.TaskExecutor;
import com.itsaky.androidide.utils.Environment;
@@ -66,15 +74,26 @@ import com.itsaky.androidide.utils.TypefaceUtils;
import com.itsaky.androidide.utils.VersionedFileManager;
import com.itsaky.androidide.views.MaterialBanner;
import com.itsaky.lsp.Diagnostic;
import com.itsaky.lsp.DidChangeTextDocumentParams;
import com.itsaky.lsp.DidChangeWatchedFilesParams;
import com.itsaky.lsp.DidCloseTextDocumentParams;
import com.itsaky.lsp.DidOpenTextDocumentParams;
import com.itsaky.lsp.DidSaveTextDocumentParams;
import com.itsaky.lsp.FileChangeType;
import com.itsaky.lsp.FileEvent;
import com.itsaky.lsp.JavaColors;
import com.itsaky.lsp.JavaReportProgressParams;
import com.itsaky.lsp.JavaStartProgressParams;
import com.itsaky.lsp.LanguageClient;
import com.itsaky.lsp.Message;
import com.itsaky.lsp.ParameterInformation;
import com.itsaky.lsp.PublishDiagnosticsParams;
import com.itsaky.lsp.ShowMessageParams;
import com.itsaky.lsp.SignatureHelp;
import com.itsaky.lsp.SignatureInformation;
import com.itsaky.lsp.TextDocumentIdentifier;
import com.itsaky.lsp.TextDocumentItem;
import com.itsaky.lsp.TextDocumentPositionParams;
import com.itsaky.toaster.Toaster;
import com.unnamed.b.atv.model.TreeNode;
import io.github.rosemoe.editor.langs.EmptyLanguage;
@@ -89,10 +108,6 @@ import java.util.Stack;
import java.util.regex.Pattern;
import me.piruin.quickaction.ActionItem;
import me.piruin.quickaction.QuickAction;
import com.itsaky.lsp.DidSaveTextDocumentParams;
import com.itsaky.lsp.DidChangeTextDocumentParams;
import com.itsaky.lsp.TextDocumentIdentifier;
import com.itsaky.lsp.JavaColors;
public class EditorActivity extends StudioActivity implements FileTreeFragment.FileActionListener,
IDEService.BuildListener,
@@ -100,7 +115,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
NavigationView.OnNavigationItemSelectedListener,
DiagnosticClickListener,
EditorFragment.FileOpenListener,
LanguageClient, CodeEditor.CursorChangeListener,
LanguageClient,
JLSRequestor {
private ActivityEditorBinding mBinding;
@@ -154,6 +169,11 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
}
};
/**
* MenuItem(s) that are related to the build process
*
* These items will be disabled once the build process starts and will be enabled after the execution
*/
private final int[] BUILD_IDS = {
R.id.menuEditor_quickRun,
R.id.menuEditor_runDebug,
@@ -162,7 +182,6 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
R.id.menuEditor_runBundle,
R.id.menuEditor_runClean,
R.id.menuEditor_runCleanBuild,
R.id.menuEditor_runRecreate,
R.id.menuEditor_lint,
R.id.menuEditor_lintDebug,
R.id.menuEditor_lintRelease
@@ -213,6 +232,17 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
KeyboardUtils.registerSoftInputChangedListener(this, __ -> onSoftInputChanged());
registerLogReceiver();
setupContainers();
setupSignatureText();
}
private void setupSignatureText() {
GradientDrawable gd = new GradientDrawable();
gd.setShape(GradientDrawable.RECTANGLE);
gd.setColor(0xff212121);
gd.setStroke(2, 0xffffffff);
gd.setCornerRadius(8);
mBinding.symbolText.setBackgroundDrawable(gd);
mBinding.symbolText.setVisibility(View.GONE);
}
private void setupContainers() {
@@ -334,13 +364,16 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
for (int id : BUILD_IDS) {
MenuItem item = menu.findItem(id);
if (item != null) {
item.setEnabled(getBuildService() != null && !getBuildService().isBuilding());
boolean enabled = getBuildService() != null && !getBuildService().isBuilding();
item.setEnabled(enabled);
item.getIcon().setAlpha(enabled ? 255 : 130);
}
}
MenuItem run1 = menu.findItem(R.id.menuEditor_quickRun);
MenuItem run2 = menu.findItem(R.id.menuEditor_run);
MenuItem undo = menu.findItem(R.id.menuEditor_undo);
MenuItem redo = menu.findItem(R.id.menuEditor_redo);
MenuItem save = menu.findItem(R.id.menuEditor_save);
if(KeyboardUtils.isSoftInputVisible(this)) {
run1.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
run2.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
@@ -352,6 +385,27 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
undo.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
redo.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
}
if(mPagerAdapter != null && mPagerAdapter.getCount() <= 0) {
undo.setEnabled(false);
redo.setEnabled(false);
save.setEnabled(false);
final int alpha = 76;
undo.getIcon().setAlpha(alpha);
redo.getIcon().setAlpha(alpha);
save.getIcon().setAlpha(alpha);
} else {
undo.setEnabled(true);
redo.setEnabled(true);
save.setEnabled(true);
final int alpha = 255;
undo.getIcon().setAlpha(alpha);
redo.getIcon().setAlpha(alpha);
save.getIcon().setAlpha(alpha);
}
return true;
}
@@ -391,8 +445,6 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
this.mCurrentFragment.undo();
} else if (id == R.id.menuEditor_redo && this.mCurrentFragment != null && this.mCurrentFragment.isVisible()) {
this.mCurrentFragment.redo();
} else if(id == R.id.menuEditor_runRecreate) {
getBuildService().recreateServices();
}
invalidateOptionsMenu();
return true;
@@ -476,7 +528,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
public void onGetDependencies(List<String> dependencies) {
setStatus(getString(R.string.msg_starting_completion));
mProject.setClassPaths(dependencies);
createCompletionServices();
createServices();
}
@Override
@@ -628,7 +680,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
}
}
private void createCompletionServices() {
private void createServices() {
new TaskExecutor().executeAsync(() -> {
getApp().createCompletionService(mProject, EditorActivity.this);
return null;
@@ -710,7 +762,77 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
public void javaColors(JavaColors colors) {
final File file = new File(colors.uri);
final EditorFragment editor = mPagerAdapter.findEditorByFile(file);
editor.setJavaColors(colors);
if(editor != null)
editor.setJavaColors(colors);
}
@Override
public void signatureHelp(SignatureHelp signature, File file) {
if(signature == null || signature.signatures == null) {
mBinding.symbolText.setVisibility(View.GONE);
return;
}
SignatureInformation info = signature.signatures.get(signature.activeSignature);
mBinding.symbolText.setText(formatSignature(info, signature.activeParameter));
final EditorFragment frag = mPagerAdapter.findEditorByFile(file);
if(frag != null) {
final CodeEditor editor = frag.getEditor();
final float[] cursor = editor.getCursorPosition();
float x = editor.updateCursorAnchor() - (mBinding.symbolText.getWidth() / 2);
float y = mBinding.editorAppBarLayout.getHeight() + (cursor[0] - editor.getRowHeight() - editor.getOffsetY() - mBinding.symbolText.getHeight());
mBinding.symbolText.setX(x);
mBinding.symbolText.setY(y);
mBinding.symbolText.setVisibility(View.VISIBLE);
//////////////////////////////////////////////
//// Position the signature text properly ////
//////////////////////////////////////////////
Rect r = new Rect();
int width = mBinding.symbolText.getWidth();
x = mBinding.symbolText.getX();
mBinding.symbolText.getWindowVisibleDisplayFrame(r);
if(r.width() != width) {
if(x < r.left) {
x = SizeUtils.dp2px(8); // an offset of 8dp from the left edge of screen
mBinding.symbolText.setX(x);
}
if(x + width > r.right) {
x = r.right - SizeUtils.dp2px(8) - width; // position to the right but leaving 8dp space from the right edge of screen
mBinding.symbolText.setX(x);
}
}
}
}
private CharSequence formatSignature(SignatureInformation signature, int paramIndex) {
String name = signature.label;
name = name.substring(0, name.indexOf("("));
SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(name, new ForegroundColorSpan(0xffffffff), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.append("(", new ForegroundColorSpan(0xff4fc3f7), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
List<ParameterInformation> params = signature.parameters;
for(int i=0;i<params.size();i++) {
int color = i == paramIndex ? 0xffff6060 : 0xffffffff;
final ParameterInformation info = params.get(i);
if(i == params.size() - 1) {
sb.append(info.label, new ForegroundColorSpan(color), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
sb.append(info.label, new ForegroundColorSpan(color), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.append(",", new ForegroundColorSpan(0xff4fc3f7), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.append(" ");
}
}
sb.append(")", new ForegroundColorSpan(0xff4fc3f7), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}
@Override
public void hideSignature() {
mBinding.symbolText.setVisibility(View.GONE);
}
@Override
@@ -735,15 +857,6 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
}
}).start();
}
@Override
public void onCursorPositionChange(int leftLine, int leftColumn, int rightLine, int rightColumn) {
if(leftLine == rightLine && leftColumn == rightColumn) {
mBinding.editorToolbar.setSubtitle(String.format("[%d, %d]", leftLine, leftColumn));
} else {
mBinding.editorToolbar.setSubtitle(String.format("[%d, %d] | [%d, %d]", leftLine, leftColumn, rightLine, rightColumn));
}
}
@Override
public void didOpen(DidOpenTextDocumentParams p) {
@@ -776,6 +889,22 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
server.didSave(params);
else addPendingMessage(createMessage(JavaLanguageServer.Method.DID_SAVE, gson.toJson(params)));
}
@Override
public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) {
final JavaLanguageServer server = getApp().getJavaLanguageServer();
if(server != null)
server.didChangeWatchedFiles(params);
else addPendingMessage(createMessage(JavaLanguageServer.Method.DID_SAVE, gson.toJson(params)));
}
@Override
public void signatureHelp(TextDocumentPositionParams params, File file) {
final JavaLanguageServer server = getApp().getJavaLanguageServer();
if(server != null)
server.signatureHelp(params, file);
else addPendingMessage(createMessage(JavaLanguageServer.Method.DID_SAVE, gson.toJson(params)));
}
private void addPendingMessage(Message msg) {
pendingMessages.push(msg);
@@ -788,6 +917,22 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
msg.params = new JsonParser().parse(data);
return msg;
}
private void notifyFileCreated(File file) {
if(!file.getName().endsWith(".java")) return;
DidChangeWatchedFilesParams p = new DidChangeWatchedFilesParams();
p.changes.add(new FileEvent(file.toURI(), FileChangeType.Created));
didChangeWatchedFiles(p);
openFile(file);
}
private void notifyFileDeleted(File file) {
if(!file.getName().endsWith(".java")) return;
DidChangeWatchedFilesParams p = new DidChangeWatchedFilesParams();
p.changes.add(new FileEvent(file.toURI(), FileChangeType.Deleted));
didChangeWatchedFiles(p);
}
/*****************************
**** Tab Related ************
@@ -905,6 +1050,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
buildView.setTypefaceLineNumber(TypefaceUtils.jetbrainsMono());
buildView.setTypefaceText(TypefaceUtils.jetbrainsMono());
buildView.setTextSize(12);
buildView.setColorScheme(new SchemeAndroidIDE());
return buildView;
}
@@ -932,6 +1078,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
logView.setTypefaceLineNumber(TypefaceUtils.jetbrainsMono());
logView.setTypefaceText(TypefaceUtils.jetbrainsMono());
logView.setTextSize(12);
buildView.setColorScheme(new SchemeAndroidIDE());
return logView;
}
@@ -970,7 +1117,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
@Override
public void openFile(File file) {
int i = mPagerAdapter.openFile(file, this, this, this);
int i = mPagerAdapter.openFile(file, this, this);
if(i >= 0 && !mBinding.tabs.getTabAt(i).isSelected())
mBinding.tabs.getTabAt(i).select();
mBinding.editorDrawerLayout.closeDrawer(GravityCompat.END);
@@ -1162,6 +1309,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
getApp().toast(R.string.msg_file_exists, Toaster.Type.ERROR);
} else {
if(FileIOUtils.writeFileFromString(file, content)) {
notifyFileCreated(file);
getApp().toast(R.string.msg_file_created, Toaster.Type.SUCCESS);
if(mLastHolded != null) {
TreeNode node = new TreeNode(file);
@@ -1229,6 +1377,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
final boolean deleted = FileUtils.delete(f);
getApp().toast(deleted ? R.string.deleted : R.string.delete_failed, deleted ? Toaster.Type.SUCCESS : Toaster.Type.ERROR);
if(deleted) {
notifyFileDeleted(f);
if(mLastHolded != null) {
TreeNode parent = mLastHolded.getParent();
parent.deleteChild(mLastHolded);
@@ -1236,6 +1385,10 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
} else {
mFileTreeFragment.listProjectFiles();
}
EditorFragment frag = mPagerAdapter.findEditorByFile(f);
if(frag != null) {
closeFile(mPagerAdapter.getFragments().indexOf(frag));
}
}
})
.setTitle(R.string.title_confirm_delete)
@@ -50,7 +50,7 @@ public class EditorPagerAdapter extends FragmentStatePagerAdapter
return null;
}
public int openFile(File file, EditorFragment.FileOpenListener listener, CodeEditor.CursorChangeListener cursorListener, JLSRequestor jlsRequestor)
public int openFile(File file, EditorFragment.FileOpenListener listener, JLSRequestor jlsRequestor)
{
int openedFileIndex = -1;
for(int i=0;i<mOpenedFiles.size();i++)
@@ -68,7 +68,6 @@ public class EditorPagerAdapter extends FragmentStatePagerAdapter
mFragments.add(EditorFragment
.newInstance(file, project)
.setFileOpenListener(listener)
.setCursorChangeListener(cursorListener)
.setJLSRequestor(jlsRequestor));
mOpenedFiles.add(file);
notifyDataSetChanged();
@@ -46,6 +46,7 @@ import com.itsaky.lsp.DidChangeConfigurationParams;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import com.itsaky.lsp.LanguageClient;
import net.lingala.zip4j.ZipFile;
public class StudioApp extends MultiDexApplication
{
@@ -169,11 +170,16 @@ public class StudioApp extends MultiDexApplication
}
}
private void extractJls() throws IOException {
private void extractJls(){
final File jlsZip = new File(Environment.JLS_HOME, "jls.zip");
ResourceUtils.copyFileFromAssets("data/jls.zip", jlsZip.getAbsolutePath());
ZipUtils.unzipFile(jlsZip, Environment.JLS_HOME);
FileUtils.delete(jlsZip);
try {
ZipFile file = new ZipFile(jlsZip, ConstantsBridge.JLS_ZIP_PASSWORD_HASH.toCharArray());
file.extractAll(Environment.JLS_HOME.getAbsolutePath());
FileUtils.delete(jlsZip);
} catch (Throwable th) {
Logger.instance("UnzipJLS").e(ThrowableUtils.getFullStackTrace(th));
}
}
private boolean setupLibsIfNeeded() {
@@ -5,6 +5,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.blankj.utilcode.util.FileIOUtils;
import com.blankj.utilcode.util.SizeUtils;
import com.itsaky.androidide.adapters.CompletionListAdapter;
import com.itsaky.androidide.databinding.FragmentEditorBinding;
import com.itsaky.androidide.fragments.preferences.EditorPreferences;
@@ -16,7 +17,7 @@ import com.itsaky.androidide.language.xml.XMLLanguage;
import com.itsaky.androidide.language.xml.lexer.XMLLexer;
import com.itsaky.androidide.models.AndroidProject;
import com.itsaky.androidide.models.ConstantsBridge;
import com.itsaky.androidide.syntax.colorschemes.SchemeWombat;
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE;
import com.itsaky.androidide.tasks.TaskExecutor;
import com.itsaky.androidide.tasks.callables.ReadFileTask;
import com.itsaky.androidide.utils.PreferenceManager;
@@ -34,7 +35,6 @@ import io.github.rosemoe.editor.interfaces.EditorEventListener;
import io.github.rosemoe.editor.langs.EmptyLanguage;
import io.github.rosemoe.editor.text.Cursor;
import io.github.rosemoe.editor.widget.CodeEditor;
import io.github.rosemoe.editor.widget.schemes.SchemeVS2019;
import java.io.File;
import java.io.StringReader;
import java.util.ArrayList;
@@ -43,8 +43,12 @@ import java.util.List;
import java.util.Map;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.Token;
import com.itsaky.androidide.utils.Logger;
import com.blankj.utilcode.util.ThrowableUtils;
import com.itsaky.lsp.TextDocumentPositionParams;
import com.itsaky.lsp.Position;
public class EditorFragment extends BaseFragment implements EditorEventListener, CodeEditor.CursorChangeListener {
public class EditorFragment extends BaseFragment implements EditorEventListener {
public FragmentEditorBinding binding;
private File mFile;
@@ -52,7 +56,6 @@ public class EditorFragment extends BaseFragment implements EditorEventListener,
private boolean isModified = false;
private boolean isFirstCreate = false;
private CodeEditor.CursorChangeListener listener;
private FileOpenListener openListener;
private JLSRequestor jlsRequestor;
private static AndroidProject project;
@@ -68,11 +71,6 @@ public class EditorFragment extends BaseFragment implements EditorEventListener,
public static final String EXT_GROOVY = ".groovy";
public static final String EXT_KOTLIN = ".kt";
public static final String EXT_JSON = ".json";
public EditorFragment setCursorChangeListener(CodeEditor.CursorChangeListener listener) {
this.listener = listener;
return this;
}
public EditorFragment setJLSRequestor(JLSRequestor requestor) {
this.jlsRequestor = requestor;
@@ -100,6 +98,10 @@ public class EditorFragment extends BaseFragment implements EditorEventListener,
this.openListener = openListener;
return this;
}
public CodeEditor getEditor() {
return binding.editorCodeEditor;
}
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -128,7 +130,9 @@ public class EditorFragment extends BaseFragment implements EditorEventListener,
binding.editorCodeEditor.setAutoCompletionOnComposing(true);
binding.editorCodeEditor.setAutoCompletionItemAdapter(new CompletionListAdapter());
binding.editorCodeEditor.setLineColorsEnabled(true);
binding.editorCodeEditor.setDividerWidth(SizeUtils.dp2px(1));
binding.editorCodeEditor.setJLSRequestor(jlsRequestor);
configureEditorIfNeeded();
new TaskExecutor().executeAsync(new ReadFileTask(mFile), result -> {
@@ -136,14 +140,6 @@ public class EditorFragment extends BaseFragment implements EditorEventListener,
postRead();
});
}
@Override
public void onCursorPositionChange(int leftLine, int leftColumn, int rightLine, int rightColumn) {
if(listener != null) {
final Cursor c = binding.editorCodeEditor. getCursor();
listener.onCursorPositionChange(c.getLeftLine(), c.getLeftColumn(), c.getRightLine(), c.getRightColumn());
}
}
public void setDiagnostics(List<Diagnostic> diags) {
if(binding.editorCodeEditor != null && diags != null) {
@@ -234,58 +230,55 @@ public class EditorFragment extends BaseFragment implements EditorEventListener,
binding.editorCodeEditor.setFile(getFile());
if (mFile.isFile() && mFile.getName().endsWith(EXT_JAVA)) {
binding.editorCodeEditor.setEditorLanguage(mJavaLanguage = new JavaLanguage(project));
binding.editorCodeEditor.setColorScheme(new SchemeVS2019());
} else if (mFile.isFile() && mFile.getName().endsWith(EXT_XML)) {
binding.editorCodeEditor.setEditorLanguage(new XMLLanguage());
binding.editorCodeEditor.setColorScheme(new SchemeWombat());
} else if (mFile.isFile() && mFile.getName().endsWith(EXT_GRADLE)) {
binding.editorCodeEditor.setEditorLanguage(new GroovyLanguage());
binding.editorCodeEditor.setColorScheme(new SchemeVS2019());
} else {
binding.editorCodeEditor.setEditorLanguage(new EmptyLanguage());
}
binding.editorCodeEditor.setColorScheme(new SchemeAndroidIDE());
isRead = true;
if(openListener != null)
openListener.onOpenSuccessful(getFile(), getText());
}
private void closeCurrentTag(String text, int line, int col) {
try {
XMLLexer lexer = new XMLLexer(CharStreams.fromReader(new StringReader(text)));
Token token;
boolean wasSlash = false, wasOpen = false;
ArrayList<String> currentNames = new ArrayList<>();
while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
final int type = token.getType();
if(type == XMLLexer.OPEN) {
wasOpen = true;
} else if(type == XMLLexer.Name) {
if(wasOpen && wasSlash && currentNames.size() > 0) {
currentNames.remove(0);
} else if(wasOpen){
currentNames.add(0, token.getText());
wasOpen = false;
}
} else if(type == XMLLexer.OPEN_SLASH) {
int l = token.getLine() - 1;
int c = token.getCharPositionInLine();
if(l == line && c == col) {
break;
}
else if(currentNames.size() > 0)
currentNames.remove(0);
} else if(type == XMLLexer.SLASH_CLOSE
|| type == XMLLexer.SPECIAL_CLOSE) {
if(currentNames.size() > 0 && token.getText().trim().endsWith("/>"))
currentNames.remove(0);
} else if(type == XMLLexer.SLASH) {
wasSlash = true;
} else wasOpen = wasSlash = false;
}
if(currentNames.size() > 0) {
binding.editorCodeEditor.getText().insert(line, col + 2, currentNames.get(0));
}
} catch (Throwable th) {}
try {
XMLLexer lexer = new XMLLexer(CharStreams.fromReader(new StringReader(text)));
Token token;
boolean wasSlash = false, wasOpen = false;
ArrayList<String> currentNames = new ArrayList<>();
while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
final int type = token.getType();
if(type == XMLLexer.OPEN) {
wasOpen = true;
} else if(type == XMLLexer.Name) {
if(wasOpen && wasSlash && currentNames.size() > 0) {
currentNames.remove(0);
} else if(wasOpen){
currentNames.add(0, token.getText());
wasOpen = false;
}
} else if(type == XMLLexer.OPEN_SLASH) {
int l = token.getLine() - 1;
int c = token.getCharPositionInLine();
if(l == line && c == col) {
break;
} else if(currentNames.size() > 0)
currentNames.remove(0);
} else if(type == XMLLexer.SLASH_CLOSE
|| type == XMLLexer.SPECIAL_CLOSE) {
if(currentNames.size() > 0 && token.getText().trim().endsWith("/>"))
currentNames.remove(0);
} else if(type == XMLLexer.SLASH) {
wasSlash = true;
} else wasOpen = wasSlash = false;
}
if(currentNames.size() > 0) {
binding.editorCodeEditor.getText().insert(line, col + 2, currentNames.get(0));
}
} catch (Throwable th) {}
}
@Override
@@ -305,52 +298,53 @@ public class EditorFragment extends BaseFragment implements EditorEventListener,
@Override
public void onNewTextSet(CodeEditor editor) {
isModified = true;
notifyChanged();
}
@Override
public void onSetSelection(int startLine, int startCol, int endLine, int endCol) {
if(jlsRequestor != null) {
jlsRequestor.hideSignature();
}
}
@Override
public void afterDelete(CodeEditor editor, CharSequence content, int startLine, int startColumn, int endLine, int endColumn, CharSequence deletedContent) {
isModified = true;
notifyChanged();
}
@Override
public void afterInsert(CodeEditor editor, CharSequence content, int startLine, int startColumn, int endLine, int endColumn, CharSequence insertedContent) {
isModified = true;
notifyChanged();
boolean isOpen = false;
try {
isOpen = editor.getText().charAt(editor.getCursor().getLeft() - 2) == '<';
} catch (Throwable th) {}
if(isOpen && insertedContent.toString().equals("/")) {
closeCurrentTag(editor.getText().toString(), endLine, endColumn);
}
if(getFile() != null && getFile().getName().endsWith(".java")) {
boolean isOpen = false;
try {
isOpen = editor.getText().charAt(editor.getCursor().getLeft() - 2) == '<';
} catch (Throwable th) {}
if(isOpen && insertedContent.toString().equals("/")) {
closeCurrentTag(editor.getText().toString(), endLine, endColumn);
}
}
char c = insertedContent.charAt(0);
if(c == '(' || c == ',') {
requestSignature();
}
}
private void requestSignature() {
if (jlsRequestor != null) {
TextDocumentPositionParams p = new TextDocumentPositionParams();
p.textDocument = new TextDocumentIdentifier(getFile().toURI());
p.position = new Position(binding.editorCodeEditor.getCursor().getLeftLine(), binding.editorCodeEditor.getCursor().getLeftColumn());
jlsRequestor.signatureHelp(p, getFile());
}
}
@Override
public void beforeReplace(CodeEditor editor, CharSequence content) {
}
private void notifyChanged() {
if (getFile() != null && getFile().getName().endsWith(EXT_JAVA) && jlsRequestor != null) {
try {
TextDocumentContentChangeEvent event = new TextDocumentContentChangeEvent();
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier();
DidChangeTextDocumentParams p = new DidChangeTextDocumentParams();
List<TextDocumentContentChangeEvent> changes = new ArrayList<>();
event.text = getText();
event.range = null;
changes.add(event);
id.uri = getFile().toURI();
id.version = VersionedFileManager.incrementVersion(getFile());
p.textDocument = id;
p.contentChanges = changes;
jlsRequestor.didChange(p);
} catch (Throwable th) {}
}
}
private void notifySaved(boolean wrote, String text) {
if (wrote && jlsRequestor != null) {
TextDocumentIdentifier id = new TextDocumentIdentifier();
@@ -24,10 +24,8 @@ import static com.itsaky.androidide.utils.PreferenceManager.*;
public class BuildPreferences extends BasePreferenceFragment implements Preference.OnPreferenceClickListener {
public static final String KEY_GRADLE_INSTALL = "idepref_build_gradleInstall";
public static final String KEY_GRADLE_COMMAMDS = "idepref_build_gradleCommands";
public static final String KEY_GRADLE_CLEAR_CACHE = "idepref_build_gradleClearCache";
public static final String KEY_CHOOSE_GRADLE = "idepref_build_chooseGradle";
private ProgressSheet progressSheet;
@@ -37,23 +35,11 @@ public class BuildPreferences extends BasePreferenceFragment implements Preferen
if(getContext() == null) return;
final PreferenceScreen screen = getPreferenceScreen();
final PreferenceCategory categoryGradle = new PreferenceCategory(getContext());
final Preference customGradle = new Preference(getContext());
final Preference chooseGradle = new Preference(getContext());
final Preference customCommands = new Preference(getContext());
final Preference clearCache = new Preference(getContext());
screen.addPreference(categoryGradle);
customGradle.setKey(KEY_GRADLE_INSTALL);
customGradle.setIcon(R.drawable.ic_language_gradle);
customGradle.setTitle(R.string.idepref_build_installgradle_title);
customGradle.setSummary(R.string.idepref_build_installgradle_summary);
chooseGradle.setKey(KEY_CHOOSE_GRADLE);
chooseGradle.setIcon(R.drawable.ic_file_rename);
chooseGradle.setTitle(R.string.idepref_build_choosegradle_title);
chooseGradle.setSummary(R.string.idepref_build_choosegradle_summary);
customCommands.setKey(KEY_GRADLE_COMMAMDS);
customCommands.setIcon(R.drawable.ic_bash_commands);
customCommands.setTitle(R.string.idepref_build_customgradlecommands_title);
@@ -65,15 +51,11 @@ public class BuildPreferences extends BasePreferenceFragment implements Preferen
clearCache.setSummary(R.string.idepref_build_clearCache_summary);
categoryGradle.setTitle(R.string.gradle);
// categoryGradle.addPreference(customGradle);
// categoryGradle.addPreference(chooseGradle);
categoryGradle.addPreference(customCommands);
categoryGradle.addPreference(clearCache);
setPreferenceScreen(screen);
customGradle.setOnPreferenceClickListener(this);
chooseGradle.setOnPreferenceClickListener(this);
customCommands.setOnPreferenceClickListener(this);
clearCache.setOnPreferenceClickListener(this);
}
@@ -81,84 +63,14 @@ public class BuildPreferences extends BasePreferenceFragment implements Preferen
@Override
public boolean onPreferenceClick(Preference p1) {
final String key = p1.getKey();
if(key.equals(KEY_GRADLE_INSTALL)) {
showInstallGradleDialog();
} else if(key.equals(KEY_GRADLE_COMMAMDS)) {
if(key.equals(KEY_GRADLE_COMMAMDS)) {
showGradleCommandsDialog();
} else if(key.equals(KEY_GRADLE_CLEAR_CACHE)) {
showClearCacheDialog();
} else if(key.equals(KEY_CHOOSE_GRADLE)) {
showChooseGradle();
}
return true;
}
private void showChooseGradle() {
final Set<String> installed = getPrefManager().getGradleFolderNames();
final String[] labels = installed.toArray(new String[installed.size()]);
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
builder.setTitle(R.string.idepref_build_choosegradle_title);
builder.setSingleChoiceItems(labels, 0, (p1, p2) -> {
DialogInterface iface = p1;
int pos = p2;
});
builder.create().show();
}
private void showInstallGradleDialog() {
final LayoutDialogTextInputBinding binding = LayoutDialogTextInputBinding.inflate(LayoutInflater.from(getContext()));
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
binding.name.setHint(R.string.zip_file_path);
builder.setTitle(R.string.idepref_build_installgradle_title);
builder.setMessage(R.string.msg_custom_gradle);
builder.setView(binding.getRoot());
builder.setPositiveButton(android.R.string.ok, (p1, p2) -> {
final String path = binding.name.getEditText().getText().toString();
if(path.trim().length() <= 0) {
StudioApp.getInstance().toast(R.string.invalid_zip, Toaster.Type.ERROR);
return;
}
File file = new File(path.trim());
if(!(file.exists() && file.isFile() && file.getName().endsWith(".zip"))) {
StudioApp.getInstance().toast(R.string.msg_file_should_be_zip, Toaster.Type.ERROR);
return;
}
p1.dismiss();
getProgressSheet().setCancelable(false);
getProgressSheet().setShowShadow(false);
getProgressSheet().setSubMessageEnabled(false);
getProgressSheet().setWelcomeTextEnabled(false);
getProgressSheet().show(getChildFragmentManager(), "custom_gradle_progress");
new TaskExecutor().executeAsync(() -> {
try {
List<File> extracted = ZipUtils.unzipFile(file, Environment.HOME);
if(extracted != null && extracted.size() > 0) {
File newestFolder = null;
for(File f : extracted) {
if((newestFolder = f.getParentFile()).getAbsolutePath().equals(Environment.HOME.getAbsolutePath())) {
break;
}
}
if(newestFolder != null) {
getPrefManager().setCurentGradleFolderName(newestFolder.getName());
Environment.GRADLE_FOLDER_NAME = newestFolder.getName();
Environment.updateGradleDir();
StudioApp.getInstance().toast(R.string.msg_gradle_installed, Toaster.Type.SUCCESS);
getProgressSheet().dismiss();
}
} else {
StudioApp.getInstance().toast(R.string.failed_unzip, Toaster.Type.ERROR);
}
} catch (Throwable th) {
StudioApp.getInstance().toast(R.string.failed_unzip, Toaster.Type.ERROR);
}
return null;
}, __ -> {});
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.create().show();
}
private void showGradleCommandsDialog() {
final String[] labels = {
"--stacktrace",
@@ -174,7 +86,7 @@ public class BuildPreferences extends BasePreferenceFragment implements Preferen
getPrefManager().isGradleScanEnabled(),
getPrefManager().isGradleWarningEnabled()
};
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext(), R.style.AppTheme_MaterialAlertDialog);
builder.setTitle(R.string.idepref_build_customgradlecommands_title);
builder.setMultiChoiceItems(labels, checked, (p1, p2, p3) -> {
boolean isChecked = p3;
@@ -197,7 +109,7 @@ public class BuildPreferences extends BasePreferenceFragment implements Preferen
}
private void showClearCacheDialog() {
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext(), R.style.AppTheme_MaterialAlertDialog);
builder.setTitle(R.string.idepref_build_clearCache_title);
builder.setMessage(R.string.msg_clear_cache);
builder.setCancelable(false);
@@ -28,7 +28,7 @@ public class ProgressSheet extends BaseBottomSheetFragment {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.progress.setIndeterminateDrawable(new FoldingCube());
binding.message.setText(message);
if(subMessageEnabled) {
binding.subMessage.setText(subMessage);
@@ -1,13 +1,22 @@
package com.itsaky.androidide.interfaces;
import com.itsaky.lsp.DidChangeTextDocumentParams;
import com.itsaky.lsp.DidChangeWatchedFilesParams;
import com.itsaky.lsp.DidCloseTextDocumentParams;
import com.itsaky.lsp.DidOpenTextDocumentParams;
import com.itsaky.lsp.DidSaveTextDocumentParams;
import com.itsaky.lsp.TextDocumentPositionParams;
import java.io.File;
public interface JLSRequestor {
void hideSignature();
void didOpen(DidOpenTextDocumentParams params);
void didClose(DidCloseTextDocumentParams params);
void didChange(DidChangeTextDocumentParams params);
void didSave(DidSaveTextDocumentParams params);
void didChangeWatchedFiles(DidChangeWatchedFilesParams params);
void signatureHelp(TextDocumentPositionParams params, File file);
}
@@ -46,6 +46,8 @@ import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import com.itsaky.lsp.DidChangeWatchedFilesParams;
import com.itsaky.lsp.SignatureHelp;
public class JavaLanguageServer implements ShellServer.Callback {
@@ -56,11 +58,13 @@ public class JavaLanguageServer implements ShellServer.Callback {
private Socket server;
private BufferedOutputStream send;
private boolean started;
private final ConcurrentHashMap<Integer, Integer> completionRequests = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Integer, Integer> formattingRequests = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Integer, File> signatureRequests = new ConcurrentHashMap<>();
private final BlockingQueue<CompletionList> completionResponseQueue = new ArrayBlockingQueue<>(20);
private final BlockingQueue<List<TextEdit>> formattingResponseQueue = new ArrayBlockingQueue<>(20);
private static final String START_COMMAND = "java " +
"--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED " +
@@ -135,6 +139,7 @@ public class JavaLanguageServer implements ShellServer.Callback {
protected void sendInit() {
InitializeParams p = new InitializeParams();
p.rootUri = new File(project.getProjectPath()).toURI();
p.roots = java.util.Set.of(p.rootUri, StudioApp.getInstance().getLogSenderDir().toURI());
initialize(p);
initialized();
@@ -156,6 +161,10 @@ public class JavaLanguageServer implements ShellServer.Callback {
});
}
public boolean isStarted() {
return started;
}
public void initialize(InitializeParams p) {
write(Method.INITIALIZE, gson.toJson(p));
}
@@ -184,6 +193,10 @@ public class JavaLanguageServer implements ShellServer.Callback {
write(Method.DID_SAVE, gson.toJson(p));
}
public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) {
write(Method.CHANGED_WATCHED_FILES, gson.toJson(params));
}
public Pair<Integer, CompletionList> completion(TextDocumentPositionParams p) {
int id = write(Method.COMPLETION, gson.toJson(p));
completionRequests.put(id, id);
@@ -209,6 +222,11 @@ public class JavaLanguageServer implements ShellServer.Callback {
write(Method.CODE_ACTION, gson.toJson(p));
}
public void signatureHelp(TextDocumentPositionParams params, File file) {
int id = write(Method.SIGNATURE_HELP, gson.toJson(params));
signatureRequests.put(id, file);
}
public void cancelRequest(int requestId) {
CancelParams p = new CancelParams();
p.id = requestId;
@@ -253,6 +271,7 @@ public class JavaLanguageServer implements ShellServer.Callback {
}
private BufferedOutputStream os;
private BufferedOutputStream os1;
private void writeOut(String data) {
try {
@@ -266,10 +285,23 @@ public class JavaLanguageServer implements ShellServer.Callback {
}
}
private void writeOut2(String data) {
try {
if(os1 == null) {
os1 = new BufferedOutputStream(new FileOutputStream(new File(FileUtil.getExternalStorageDir(), "ide_xlog/verbose.txt"), true));
}
os1.write(data.getBytes());
os1.flush();
} catch (Throwable th) {
logger.e(ThrowableUtils.getFullStackTrace(th));
}
}
/**
* This method is called on UI Thread, do not perform time consuming or networking tasks
*/
private void onServerOut(String line) {
writeOut2(line + "\n");
if(line.contains(CONTENT_LENGTH)) line = line.substring(0, line.lastIndexOf(CONTENT_LENGTH));
if(this.client == null) return;
try {
@@ -277,7 +309,9 @@ public class JavaLanguageServer implements ShellServer.Callback {
JsonObject obj = new JsonParser().parse(line.trim()).getAsJsonObject();
if(obj.has(Key.METHOD)) {
final String method = obj.get(Key.METHOD).getAsString();
if(method.equals(Method.PUBLISH_DIAGNOSTICS)) {
if(method.equals(Method.REGISTER_CAPABILITY)) {
started = true;
} else if(method.equals(Method.PUBLISH_DIAGNOSTICS)) {
PublishDiagnosticsParams params = gson.fromJson(obj.get(Key.PARAMS).toString(), PublishDiagnosticsParams.class);
client.publishDiagnostics(params);
} else if(method.equals(Method.JLS_PROGRESS_START)) {
@@ -290,6 +324,7 @@ public class JavaLanguageServer implements ShellServer.Callback {
client.javaProgressEnd();
} else if(method.equals(Method.JAVA_COLORS)) {
JavaColors colors = gson.fromJson(obj.get(Key.PARAMS).toString(), JavaColors.class);
logger.v(colors.toString());
client.javaColors(colors);
}
} else if(obj.has(Key.ID)) {
@@ -298,11 +333,15 @@ public class JavaLanguageServer implements ShellServer.Callback {
final CompletionList list = gson.fromJson(obj.get(Key.RESULT).getAsJsonObject(), CompletionList.class);
completionResponseQueue.put(list);
} else if(formattingRequests.containsKey(id)) {
final List<TextEdit> list = gson.fromJson(obj.get(Key.RESULT).getAsJsonObject(), TypeToken.getParameterized(List.class, TextEdit.class).getType());
formattingResponseQueue.put(list);
// TODO: Implement this
} else if(signatureRequests.containsKey(id)) {
try {
SignatureHelp signature = gson.fromJson(obj.get(Key.RESULT).getAsJsonObject(), SignatureHelp.class);
client.signatureHelp(signature, signatureRequests.get(id));
} catch ( Throwable th) {
client.signatureHelp(null, null);
}
}
} else {
}
} catch (Throwable th) {
logger.e("onServerOut", line, ThrowableUtils.getFullStackTrace(th));
@@ -346,6 +385,8 @@ public class JavaLanguageServer implements ShellServer.Callback {
public static final String PUBLISH_DIAGNOSTICS = "textDocument/publishDiagnostics";
public static final String JAVA_COLORS = "java/colors";
public static final String REGISTER_CAPABILITY = "client/registerCapability";
}
public static class Key {
@@ -62,7 +62,7 @@ public class XMLAnalyzer implements CodeAnalyzer {
addHexColorIfPresent(token, lineColors, line, column);
break;
case XMLLexer.Name :
colors.addIfNeeded(line, column, previous.getType() == XMLLexer.OPEN || previous.getType() == XMLLexer.OPEN_SLASH ? EditorColorScheme.IDENTIFIER_NAME : EditorColorScheme.TEXT_NORMAL);
colors.addIfNeeded(line, column, previous.getType() == XMLLexer.OPEN || previous.getType() == XMLLexer.OPEN_SLASH ? EditorColorScheme.XML_TAG : EditorColorScheme.TEXT_NORMAL);
addHexColorIfPresent(token, lineColors, line, column);
break;
case XMLLexer.TEXT :
@@ -37,7 +37,9 @@ public class XMLLanguage implements EditorLanguage {
@Override
public boolean isAutoCompleteChar(char ch) {
return JavaCharacter.isJavaIdentifierPart(ch) || ch == '<' || ch == '/';
return JavaCharacter.isJavaIdentifierPart(ch)
|| ch == '<'
|| ch == '/';
}
@Override
@@ -21,6 +21,7 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.itsaky.androidide.utils.Logger;
public class XMLCompletionService {
private HashMap<String, Attr> attrs;
@@ -68,19 +69,19 @@ public class XMLCompletionService {
}
return handleResults(result);
} else {
IsInValueScanner scanner = new IsInValueScanner(editor.getCursor().getLeft());
String name = scanner.scan(editor.getText().toString());
final IsInValueScanner scanner = new IsInValueScanner(editor.getCursor().getLeft());
final String name = scanner.scan(editor.getText().toString());
if(name != null) {
final String attrName = name.contains(":") ? name.substring(name.indexOf(":") + 1) : name;
if(attrs.containsKey(attrName)) {
Attr attr = attrs.get(attrName);
if(attr.hasPossibleValues()) {
Set<String> values = attr.possibleValues;
for(String value : values)
if(value.toLowerCase(Locale.US).contains(prefix))
result.add(valueAsCompletion(value));
}
}
if (attrs.containsKey(attrName)) {
Attr attr = attrs.get(attrName);
if(attr.hasPossibleValues()) {
Set<String> values = attr.possibleValues;
for(String value : values)
if(value.toLowerCase(Locale.US).contains(prefix))
result.add(valueAsCompletion(value));
}
}
} else {
for(Map.Entry<String, Attr> entry : attrs.entrySet()) {
Attr attr = entry.getValue();
@@ -187,10 +188,10 @@ public class XMLCompletionService {
private class IsInValueScanner {
private int cursorIndex;
public IsInValueScanner(int cursorIndex) {
this.cursorIndex = cursorIndex;
}
}
private boolean containsCursor(Token token) {
int start = token.getStartIndex();
@@ -205,9 +206,9 @@ public class XMLCompletionService {
String attrName = null;
while((token = lexer.nextToken()) != null && token.getType() != XMLLexer.EOF) {
if(token.getType() == XMLLexer.STRING && containsCursor(token)) {
String text = token.getText();
if(text.startsWith("\""))
return attrName;
String text = token.getText();
if(text.startsWith("\""))
return attrName;
} else if(token.getType() == XMLLexer.Name) {
attrName = token.getText();
}
@@ -1,10 +1,14 @@
package com.itsaky.androidide.models;
import com.blankj.utilcode.util.ThrowableUtils;
import com.itsaky.androidide.app.StudioApp;
import com.itsaky.androidide.language.java.server.JavaLanguageServer;
import com.itsaky.androidide.utils.Logger;
import com.itsaky.lsp.CompletionItem;
import com.itsaky.lsp.CompletionItemKind;
import com.itsaky.lsp.Position;
import com.itsaky.lsp.TextDocumentIdentifier;
import com.itsaky.lsp.TextDocumentPositionParams;
import com.itsaky.lsp.TextEdit;
import io.github.rosemoe.editor.text.Cursor;
import io.github.rosemoe.editor.widget.CodeEditor;
@@ -62,8 +66,10 @@ public class CompletionItemWrapper implements SuggestItem, Comparable {
editor.getText().delete(cursor.getLeftLine(), cursor.getLeftColumn() - length, cursor.getLeftLine(), cursor.getLeftColumn());
cursor.onCommitText(text);
if(shiftLeft && !atEnd)
if(shiftLeft && !atEnd) {
editor.moveSelectionLeft();
requestSignature(editor);
}
final List<TextEdit> edits = item.additionalTextEdits;
if(edits != null && edits.size() > 0) {
@@ -84,6 +90,16 @@ public class CompletionItemWrapper implements SuggestItem, Comparable {
Logger.instance("CompletionItemWrapper").e("onSelectThis, Error: ", ThrowableUtils.getFullStackTrace(th));
}
}
private void requestSignature(CodeEditor editor) {
final JavaLanguageServer server = StudioApp.getInstance().getJavaLanguageServer();
if (server != null) {
TextDocumentPositionParams p = new TextDocumentPositionParams();
p.textDocument = new TextDocumentIdentifier(editor.getFile().toURI());
p.position = new Position(editor.getCursor().getLeftLine(), editor.getCursor().getLeftColumn());
server.signatureHelp(p, editor.getFile());
}
}
@Override
public int compareTo(Object p1) {
@@ -10,4 +10,9 @@ public class ConstantsBridge {
public static boolean CLASS_LOAD_SUCCESS = true;
public static List<String> PROJECT_DEXES = null;
// Password unzipping the JLS stored in assets
// Real password is admin@androidide.com
// This will he further encrypted by StringFog at compile time
public static final String JLS_ZIP_PASSWORD_HASH = "865dabea6f06fea1a3dd572e58a4a81c";
}
@@ -0,0 +1,60 @@
package com.itsaky.androidide.syntax.colorschemes;
import io.github.rosemoe.editor.widget.EditorColorScheme;
public class SchemeAndroidIDE extends EditorColorScheme {
@Override
public void applyDefault() {
super.applyDefault();
setColor(WHOLE_BACKGROUND, 0xff212121);
setColor(LINE_NUMBER_BACKGROUND, 0xff212121);
setColor(LINE_DIVIDER, 0xff9e9e9e);
setColor(LINE_NUMBER, 0xff424242);
setColor(LINE_NUMBER_PANEL, 0xff000000);
setColor(LINE_NUMBER_PANEL_TEXT, 0xffffffff);
setColor(TEXT_NORMAL, 0xfff5f5f5);
setColor(SELECTED_TEXT_BACKGROUND, 0xff757575);
setColor(TEXT_SELECTED, 0xff424242);
setColor(SELECTION_INSERT, 0xffff5252);
setColor(SELECTION_HANDLE, 0xffff5252);
setColor(CURRENT_LINE, 0xff313131);
setColor(UNDERLINE, 0xffffffff);
setColor(SCROLL_BAR_THUMB, 0xff757575);
setColor(SCROLL_BAR_THUMB_PRESSED, 0xffff5252);
setColor(SCROLL_BAR_TRACK, 0xffbdbdbd);
setColor(BLOCK_LINE, 0xff424242);
setColor(BLOCK_LINE_CURRENT, 0xffffffff);
setColor(AUTO_COMP_PANEL_BG, 0xff757575);
setColor(AUTO_COMP_PANEL_CORNER, 0xff9e9e9e);
setColor(MATCHED_TEXT_BACKGROUND, 0xffffff00);
setColor(NON_PRINTABLE_CHAR, 0xffdddddd);
setColor(KEYWORD, 0xffff6060);
setColor(COMMENT, 0xffbdbdbd);
setColor(OPERATOR, 0xff4fc3f7);
setColor(LITERAL, 0xff8bc34a);
setColor(TYPE_NAME, 0xff4fc3f7);
setColor(LOCAL_VARIABLE, 0xfff5f5f5);
setColor(RESOURCE_VARIABLE, 0xfff5f5f5);
setColor(PARAMETER, 0xfff5f5f5);
setColor(EXCEPTION_PARAM, 0xfff5f5f5);
setColor(METHOD, 0xfff5f5f5);
setColor(CONSTRUCTOR, 0xfff5f5f5);
setColor(ANNOTATION, 0xff4fc3f7);
setColor(PACKAGE_NAME, 0xfff0be4b);
setColor(FIELD, 0xfff0be4b);
setColor(STATIC_INIT, 0xfff0be4b);
setColor(INSTANCE_INIT, 0xfff0be4b);
setColor(TYPE_PARAM, 0xfff0be4b);
setColor(STATIC_FIELD, 0xffffb300);
setColor(ENUM_TYPE, 0xff4fc3f7);
setColor(INTERFACE, 0xff4fc3f7);
setColor(ENUM, 0xffffb300);
setColor(XML_TAG, 0xffff6060);
setColor(DIAGNOSTIC_ERROR, 0xfff44336);
setColor(DIAGNOSTIC_WARNING, 0xffFFEB3B);
setColor(DIAGNOSTIC_INFO, 0xff4CAF50);
setColor(DIAGNOSTIC_HINT, 0xffffffff);
}
}
@@ -18,13 +18,13 @@ public class SchemeWombat extends EditorColorScheme {
setColor(LINE_DIVIDER, 0xff656565);
setColor(COMMENT, 0xff99968b);
setColor(NON_PRINTABLE_CHAR, 0xff99968b);
setColor(IDENTIFIER_NAME, 0xfff08080);
setColor(TYPE_NAME, 0xfff08080);
setColor(ANNOTATION, 0xff808080);
setColor(OPERATOR, 0xfff3f6ee);
setColor(FUNCTION_NAME, 0xfff3f6ee);
setColor(METHOD, 0xfff3f6ee);
setColor(LITERAL, 0xff96e454);
setColor(OPERATOR, 0xff8ac6f2);
setColor(IDENTIFIER_VAR, 0xffd4c4a9);
setColor(LOCAL_VARIABLE, 0xffd4c4a9);
setColor(SELECTION_HANDLE, 0xfff44336);
}
}
@@ -210,7 +210,7 @@ public class GroovyLexerImpl extends BaseJavaLexer implements Lexer {
case GroovyLexer.LONG:
case GroovyLexer.SHORT:
type = TokenType.TYPE;
colors.addIfNeeded(line, column, EditorColorScheme.IDENTIFIER_NAME);
colors.addIfNeeded(line, column, EditorColorScheme.TYPE_NAME);
wasClassName = true;
break;
@@ -235,7 +235,7 @@ public class GroovyLexerImpl extends BaseJavaLexer implements Lexer {
}
if ((previous == GroovyLexer.IDENTIFIER || builtinTypes.contains(previous)) && wasClassName) {
colors.addIfNeeded(line, column, EditorColorScheme.IDENTIFIER_VAR);
colors.addIfNeeded(line, column, EditorColorScheme.LOCAL_VARIABLE);
wasClassName = false;
break;
}
@@ -5,6 +5,7 @@ import com.itsaky.androidide.syntax.lexer.Lexer;
import com.itsaky.androidide.syntax.lexer.impls.BaseJavaLexer;
import com.itsaky.androidide.syntax.lexer.tokens.Token;
import com.itsaky.androidide.syntax.lexer.tokens.TokenType;
import com.itsaky.lsp.JavaColors;
import com.itsaky.lsp.Range;
import io.github.rosemoe.editor.struct.BlockLine;
import io.github.rosemoe.editor.text.TextAnalyzeResult;
@@ -14,7 +15,6 @@ import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.CharStreams;
import com.itsaky.lsp.JavaColors;
public class JavaLexerImpl extends BaseJavaLexer implements Lexer {
@@ -214,7 +214,7 @@ public class JavaLexerImpl extends BaseJavaLexer implements Lexer {
case JavaLexer.LONG:
case JavaLexer.SHORT:
type = TokenType.TYPE;
colors.addIfNeeded(line, column, EditorColorScheme.IDENTIFIER_NAME);
colors.addIfNeeded(line, column, EditorColorScheme.TYPE_NAME);
wasClassName = true;
break;
@@ -232,33 +232,91 @@ public class JavaLexerImpl extends BaseJavaLexer implements Lexer {
case JavaLexer.IDENTIFIER :
type = TokenType.IDENTIFIER;
if (previous == JavaLexer.AT) {
colors.addIfNeeded(line, column, EditorColorScheme.ANNOTATION);
wasClassName = false;
break;
}
if ((previous == JavaLexer.IDENTIFIER || builtinTypes.contains(previous)) && wasClassName) {
colors.addIfNeeded(line, column, EditorColorScheme.IDENTIFIER_VAR);
wasClassName = false;
break;
}
if(isClassName(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.IDENTIFIER_NAME);
break;
}
if(isFieldOrStatic(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.FIELD);
break;
}
if(isPackageName(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.PACKAGE_NAME);
break;
}
if(isEnumType(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.ENUM_TYPE);
break;
}
if(isClassName(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.TYPE_NAME);
break;
}
if(isAnnotationType(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.ANNOTATION);
break;
}
if(isInterface(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.INTERFACE);
break;
}
if(isEnum(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.ENUM);
break;
}
if(isStaticField(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.STATIC_FIELD);
break;
}
if(isField(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.FIELD);
break;
}
if(isParameter(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.PARAMETER);
break;
}
if(isLocal(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.LOCAL_VARIABLE);
break;
}
if(isExceptionParam(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.EXCEPTION_PARAM);
break;
}
if(isMethod(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.METHOD);
break;
}
if(isConstructor(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.CONSTRUCTOR);
break;
}
if(isStaticInit(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.STATIC_INIT);
break;
}
if(isInstanceInit(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.INSTANCE_INIT);
break;
}
if(isTypeParam(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.TYPE_PARAM);
break;
}
if(isResourceVariable(line, column)) {
colors.addIfNeeded(line, column, EditorColorScheme.RESOURCE_VARIABLE);
break;
}
colors.addIfNeeded(line, column, EditorColorScheme.TEXT_NORMAL);
break;
case JavaLexer.LBRACE :
@@ -306,61 +364,96 @@ public class JavaLexerImpl extends BaseJavaLexer implements Lexer {
return type;
}
private boolean isEnumType(int line, int column) {
if(javaColors == null || javaColors.enumTypes == null) return false;
return isInRange(javaColors.enumTypes, line, column);
}
private boolean isAnnotationType(int line, int column) {
if(javaColors == null || javaColors.annotationTypes == null) return false;
return isInRange(javaColors.annotationTypes, line, column);
}
private boolean isInterface(int line, int column) {
if(javaColors == null || javaColors.interfaces == null) return false;
return isInRange(javaColors.interfaces, line, column);
}
private boolean isEnum(int line, int column) {
if(javaColors == null || javaColors.enums == null) return false;
return isInRange(javaColors.enums, line, column);
}
private boolean isParameter(int line, int column) {
if(javaColors == null || javaColors.parameters == null) return false;
return isInRange(javaColors.parameters, line, column);
}
private boolean isExceptionParam(int line, int column) {
if(javaColors == null || javaColors.exceptionParams == null) return false;
return isInRange(javaColors.exceptionParams, line, column);
}
private boolean isConstructor(int line, int column) {
if(javaColors == null || javaColors.constructors == null) return false;
return isInRange(javaColors.constructors, line, column);
}
private boolean isStaticInit(int line, int column) {
if(javaColors == null || javaColors.staticInits == null) return false;
return isInRange(javaColors.staticInits, line, column);
}
private boolean isInstanceInit(int line, int column) {
if(javaColors == null || javaColors.instanceInits == null) return false;
return isInRange(javaColors.instanceInits, line, column);
}
private boolean isTypeParam(int line, int column) {
if(javaColors == null || javaColors.typeParams == null) return false;
return isInRange(javaColors.typeParams, line, column);
}
private boolean isResourceVariable(int line, int column) {
if(javaColors == null || javaColors.resourceVariables == null) return false;
return isInRange(javaColors.resourceVariables, line, column);
}
private boolean isPackageName(int line, int column) {
if(javaColors == null || javaColors.packages == null) return false;
final List<Range> packages = javaColors.packages;
if(packages != null && packages.size() > 0) {
for(int i=0;i<packages.size();i++) {
final Range range = packages.get(i);
if(range == null) continue;
if(range.start.line == line && range.start.character == column)
return true;
}
}
return false;
return isInRange(javaColors.packages, line, column);
}
private boolean isClassName(int line, int column) {
if(javaColors == null || javaColors.classNames == null) return false;
final List<Range> names = javaColors.classNames;
if(names != null && names.size() > 0) {
for(int i=0;i<names.size();i++) {
final Range range = names.get(i);
if(range == null) continue;
if(range.start.line == line && range.start.character == column)
return true;
}
}
return false;
}
private boolean isFieldOrStatic(int line, int column) {
return isField(line, column) || isStatic(line, column);
return isInRange(javaColors.classNames, line, column);
}
private boolean isField(int line, int column) {
if(javaColors == null || javaColors.fields == null) return false;
final List<Range> fields = javaColors.fields;
if(fields != null && fields.size() > 0) {
for(int i=0;i<fields.size();i++) {
final Range range = fields.get(i);
if(range == null) continue;
if(range.start.line == line && range.start.character == column)
return true;
}
}
return false;
return isInRange(javaColors.fields, line, column);
}
private boolean isStatic(int line, int column) {
private boolean isStaticField(int line, int column) {
if(javaColors == null || javaColors.statics == null) return false;
final List<Range> statics = javaColors.statics;
if(statics != null && statics.size() > 0) {
for(int i=0;i<statics.size();i++) {
final Range range = statics.get(i);
return isInRange(javaColors.statics, line, column);
}
private boolean isMethod(int line, int column) {
if(javaColors == null || javaColors.methods == null) return false;
return isInRange(javaColors.methods, line, column);
}
private boolean isLocal(int line, int column) {
if(javaColors == null || javaColors.locals == null) return false;
return isInRange(javaColors.locals, line, column);
}
private boolean isInRange(List<Range> ranges, int line, int column) {
if(ranges != null && ranges.size() > 0) {
for(int i=0;i<ranges.size();i++) {
final Range range = ranges.get(i);
if(range == null) continue;
if(range.start.line == line && range.start.character == column)
return true;
@@ -18,7 +18,7 @@ public class Logger {
}
public static Logger instance(String tag) {
return instance == null ? createInstance(tag) : instance;
return createInstance(tag);
}
private Logger(String tag) {
@@ -109,7 +109,7 @@ public class PreferenceManager {
}
public boolean isGradleInfoEnabled() {
return getBoolean(KEY_GRADLECMD_INFO);
return getBoolean(KEY_GRADLECMD_INFO, true);
}
public boolean isGradleDebugEnabled() {
@@ -12,4 +12,8 @@ public class TypefaceUtils {
public static Typeface jetbrainsMono() {
return Typeface.createFromAsset(StudioApp.getInstance().getAssets(), "fonts/jetbrains-mono.ttf");
}
public static Typeface josefinSans() {
return Typeface.createFromAsset(StudioApp.getInstance().getAssets(), "fonts/josefin-sans.ttf");
}
}
@@ -0,0 +1,52 @@
package com.itsaky.androidide.views;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.LinearLayout;
import android.graphics.Path;
import android.graphics.Paint;
import android.graphics.Color;
public class TooltipLayout extends LinearLayout {
private final float dp8;
public TooltipLayout (Context ctx) {
this(ctx, null);
}
public TooltipLayout (Context ctx, AttributeSet attrs) {
this(ctx, attrs, 0);
}
public TooltipLayout (Context ctx, AttributeSet attrs, int style) {
super(ctx, attrs, style);
dp8 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics());
}
@Override
protected void onDraw(Canvas canvas) {
final int width = getWidth();
final int height = getHeight();
final float midX = width / 2;
Path path = new Path();
path.moveTo(0, 0);
path.lineTo(width, 0);
path.lineTo(width, height - dp8);
path.lineTo(midX + dp8, height - dp8);
path.lineTo(midX, height );
path.lineTo(midX - dp8, height - dp8);
path.lineTo(0, height - dp8);
path.close();
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#424242"));
canvas.drawPath(path, paint);
super.onDraw(canvas);
}
}
@@ -66,5 +66,6 @@ public interface EditorEventListener {
* Note:do not change content at this time
*/
void beforeReplace(CodeEditor editor, CharSequence content);
void onSetSelection(int startLine, int startCol, int endLine, int endCol);
}
@@ -58,12 +58,18 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.core.content.ContextCompat;
import com.itsaky.androidide.R;
import com.itsaky.androidide.app.StudioApp;
import com.itsaky.androidide.interfaces.JLSRequestor;
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE;
import com.itsaky.androidide.utils.TypefaceUtils;
import com.itsaky.androidide.utils.VersionedFileManager;
import com.itsaky.lsp.Diagnostic;
import com.itsaky.lsp.DiagnosticSeverity;
import com.itsaky.lsp.DidChangeTextDocumentParams;
import com.itsaky.lsp.Position;
import com.itsaky.lsp.Range;
import com.itsaky.lsp.TextDocumentContentChangeEvent;
import com.itsaky.lsp.VersionedTextDocumentIdentifier;
import io.github.rosemoe.editor.interfaces.EditorEventListener;
import io.github.rosemoe.editor.interfaces.EditorLanguage;
import io.github.rosemoe.editor.interfaces.NewlineHandler;
@@ -91,7 +97,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.itsaky.lsp.DiagnosticSeverity;
/**
* CodeEditor is a editor that can highlight text regions by doing basic syntax analyzing
@@ -495,8 +500,11 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
setLineNumberEnabled(true);
setLineColorsEnabled(true);
setAutoCompletionOnComposing(true);
setTypefaceText(Typeface.DEFAULT);
setTypefaceText(TypefaceUtils.jetbrainsMono());
setTypefaceLineNumber(TypefaceUtils.jetbrainsMono());
setPinLineNumber(true);
setLineNumberAlign(Paint.Align.RIGHT);
setColorScheme(new SchemeAndroidIDE());
// Issue #41 View being highlighted when focused on Android 11
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setDefaultFocusHighlightEnabled(false);
@@ -1472,18 +1480,14 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
}
private int diagnosticColor(int severity) {
int id = R.color.diagnostic_warning;
switch(id) {
case DiagnosticSeverity.Error:
id = R.color.diagnostic_error;
break;
default:
id = R.color.diagnostic_warning;
break;
int id = EditorColorScheme.DIAGNOSTIC_HINT;
switch(severity) {
case DiagnosticSeverity.Error : id = EditorColorScheme.DIAGNOSTIC_ERROR; break;
case DiagnosticSeverity.Warning : id = EditorColorScheme.DIAGNOSTIC_WARNING; break;
case DiagnosticSeverity.Information : id = EditorColorScheme.DIAGNOSTIC_INFO; break;
default : id = EditorColorScheme.DIAGNOSTIC_ERROR; break;
}
final Context ctx = StudioApp.getInstance();
return ContextCompat.getColor(ctx, id);
return mColors.getColor(id);
}
protected void showTextActionPopup() {
@@ -2398,7 +2402,7 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
private void updateDiagnosticWindowPosition() {
float panelX = updateCursorAnchor() + mDpUnit * 20;
float[] rightLayoutOffset = mLayout.getCharLayoutOffset(mCursor.getRightLine(), mCursor.getRightColumn());
float panelY = rightLayoutOffset[0] - getOffsetY() + getRowHeight() / 2f;
float panelY = rightLayoutOffset[0] - getOffsetY() - getRowHeight();
float restY = getHeight() - panelY;
if (restY > mDpUnit * 120) {
restY = mDpUnit * 120;
@@ -2420,8 +2424,9 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
int w = getWidth() / 3;
mDiagnosticWindow.setWidth(w * 2);
}
mDiagnosticWindow.setHeight((int) restY);
mDiagnosticWindow.setExtendedY(panelY - restY);
mDiagnosticWindow.updatePosition();
}
@@ -2468,7 +2473,7 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
*
* @return The offset x of right cursor on view
*/
protected float updateCursorAnchor() {
public float updateCursorAnchor() {
CursorAnchorInfo.Builder builder = mAnchorInfoBuilder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.reset();
@@ -2705,6 +2710,10 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
public long getPointPosition(float xOffset, float yOffset) {
return mLayout.getCharPositionForLayoutOffset(xOffset - measureTextRegionOffset(), yOffset);
}
public float[] getCursorPosition() {
return mLayout.getCharLayoutOffset(getCursor().getLeftLine(), getCursor().getLeftColumn());
}
/**
* Determine character position using positions on view
@@ -3513,9 +3522,9 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
showOrHideDiagnosticWindow();
if(mCursorChangeListener != null) {
final Cursor c = getCursor();
mCursorChangeListener.onCursorPositionChange(c.getLeftLine(), c.getLeftColumn(), c.getRightLine(), c.getRightColumn());
if(mListener != null) {
Cursor c = getCursor();
mListener.onSetSelection(c.getLeftLine(), c.getLeftColumn(), c.getRightLine(), c.getRightColumn());
}
}
@@ -3594,21 +3603,11 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
mEventHandler.notifyTouchedSelectionHandlerLater();
showOrHideDiagnosticWindow();
if(mCursorChangeListener != null) {
final Cursor c = getCursor();
mCursorChangeListener.onCursorPositionChange(c.getLeftLine(), c.getLeftColumn(), c.getRightLine(), c.getRightColumn());
if(mListener != null) {
Cursor c = getCursor();
mListener.onSetSelection(c.getLeftLine(), c.getLeftColumn(), c.getRightLine(), c.getRightColumn());
}
}
private CursorChangeListener mCursorChangeListener;
public void setCursorChangeListener(CursorChangeListener listener ){
this.mCursorChangeListener = listener;
}
public static interface CursorChangeListener {
void onCursorPositionChange(int leftLine, int leftColumn, int rightLine, int rightColumn);
}
/**
* Move to next page
@@ -3729,6 +3728,9 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
if (mListener != null) {
mListener.onNewTextSet(this);
}
notifyChanged();
if (mInputMethodManager != null) {
mInputMethodManager.restartInput(this);
}
@@ -4386,16 +4388,19 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
mListener.beforeReplace(this, content);
}
}
private JLSRequestor jlsRequestor;
public void setJLSRequestor(JLSRequestor requestor) {
this.jlsRequestor = requestor;
}
@Override
public void afterInsert(Content content, int startLine, int startColumn, int endLine, int endColumn, CharSequence insertedContent) {
if(mDiagnosticWindow != null)
mDiagnosticWindow.hide();
// Notify listener
if (mListener != null) {
mListener.afterInsert(this, mText, startLine, startColumn, endLine, endColumn, insertedContent);
}
notifyChanged();
// Update spans
if (isSpanMapPrepared(true, endLine - startLine)) {
@@ -4449,6 +4454,28 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
// Notify to update highlight
mSpanner.analyze(mText);
mEventHandler.hideInsertHandle();
// Notify listener
if (mListener != null) {
mListener.afterInsert(this, mText, startLine, startColumn, endLine, endColumn, insertedContent);
}
}
private void notifyChanged() {
if (getFile() != null && getFile().getName().endsWith(".java") && jlsRequestor != null) {
TextDocumentContentChangeEvent event = new TextDocumentContentChangeEvent();
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier();
DidChangeTextDocumentParams p = new DidChangeTextDocumentParams();
List<TextDocumentContentChangeEvent> changes = new ArrayList<>();
event.text = getText().toString();
event.range = null;
changes.add(event);
id.uri = getFile().toURI();
id.version = VersionedFileManager.incrementVersion(getFile());
p.textDocument = id;
p.contentChanges = changes;
jlsRequestor.didChange(p);
}
}
@Override
@@ -4456,9 +4483,7 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
if(mDiagnosticWindow != null)
mDiagnosticWindow.hide();
if (mListener != null) {
mListener.afterDelete(this, mText, startLine, startColumn, endLine, endColumn, deletedContent);
}
notifyChanged();
if (isSpanMapPrepared(false, endLine - startLine)) {
if (startLine == endLine) {
@@ -4498,6 +4523,10 @@ public class CodeEditor extends View implements ContentListener, TextAnalyzer.Ca
mSpanner.analyze(mText);
mEventHandler.hideInsertHandle();
}
if (mListener != null) {
mListener.afterDelete(this, mText, startLine, startColumn, endLine, endColumn, deletedContent);
}
}
@Override
@@ -46,10 +46,10 @@ public class DiagnosticWindow extends EditorBasePopupWindow {
binding.errorPosition.setText(
editor.getContext().getString(
com.itsaky.androidide.R.string.diagnostic_position,
""+ diagnostic.range.start.line + 1,
""+ diagnostic.range.start.character + 1,
""+ diagnostic.range.end.line + 1,
""+ diagnostic.range.end.character + 1
""+ (diagnostic.range.start.line + 1),
""+ (diagnostic.range.start.character + 1),
""+ (diagnostic.range.end.line + 1),
""+ (diagnostic.range.end.character + 1)
)
);
@@ -52,6 +52,11 @@ import io.github.rosemoe.editor.util.Objects;
*/
public class EditorColorScheme {
public static final int DIAGNOSTIC_ERROR = 38;
public static final int DIAGNOSTIC_WARNING = 39;
public static final int DIAGNOSTIC_HINT = 40;
public static final int DIAGNOSTIC_INFO = 41;
public static final int LOG_DEBUG = 5; // Text Normal
public static final int LOG_INFO = 32;
public static final int LOG_ERROR = 33;
@@ -59,13 +64,24 @@ public class EditorColorScheme {
//-----------------Highlight colors-----------
public static final int XML_TAG = 52;
public static final int FIELD = 35;
public static final int STATIC_FIELD = 36;
public static final int PACKAGE_NAME = 37;
public static final int ENUM_TYPE = 42;
public static final int INTERFACE = 43;
public static final int ENUM = 44;
public static final int PARAMETER = 45;
public static final int CONSTRUCTOR = 46;
public static final int STATIC_INIT = 47;
public static final int INSTANCE_INIT = 48;
public static final int TYPE_PARAM = 49;
public static final int RESOURCE_VARIABLE = 50;
public static final int EXCEPTION_PARAM = 51;
public static final int ANNOTATION = 28;
public static final int FUNCTION_NAME = 27;
public static final int IDENTIFIER_NAME = 26;
public static final int IDENTIFIER_VAR = 25;
public static final int METHOD = 27;
public static final int TYPE_NAME = 26;
public static final int LOCAL_VARIABLE = 25;
public static final int LITERAL = 24;
public static final int OPERATOR = 23;
public static final int COMMENT = 22;
@@ -110,7 +126,7 @@ public class EditorColorScheme {
/**
* Max pre-defined color id
*/
protected static final int END_COLOR_ID = 37;
protected static final int END_COLOR_ID = 52;
/**
* Real color saver
*/
@@ -156,22 +172,6 @@ public class EditorColorScheme {
for (int i = START_COLOR_ID; i <= END_COLOR_ID; i++) {
applyDefault(i);
}
setColor(WHOLE_BACKGROUND, 0xff1e1e1e);
setColor(TEXT_NORMAL, 0xffdcdcdc);
setColor(LINE_NUMBER_BACKGROUND, 0xff1e1e1e);
setColor(LINE_NUMBER, 0xff2b9eaf);
setColor(LINE_DIVIDER, 0xff2b9eaf);
setColor(SCROLL_BAR_THUMB, 0xff3e3e42);
setColor(SCROLL_BAR_THUMB_PRESSED, 0xff9e9e9e);
setColor(SELECTED_TEXT_BACKGROUND, 0xff3676b8);
setColor(MATCHED_TEXT_BACKGROUND, 0xff653306);
setColor(CURRENT_LINE, 0xff464646);
setColor(SELECTION_INSERT, 0xffffffff);
setColor(SELECTION_HANDLE, 0xffffffff);
setColor(BLOCK_LINE, 0xff717171);
setColor(BLOCK_LINE_CURRENT, 0);
setColor(NON_PRINTABLE_CHAR, 0xffdddddd);
}
/**
@@ -250,9 +250,15 @@ public class EditorColorScheme {
case BLOCK_LINE_CURRENT:
color = 0xff999999;
break;
case IDENTIFIER_VAR:
case IDENTIFIER_NAME:
case FUNCTION_NAME:
case LOCAL_VARIABLE:
case TYPE_NAME:
case TYPE_PARAM :
case PARAMETER :
case METHOD:
case ENUM_TYPE :
case INTERFACE :
case CONSTRUCTOR :
case EXCEPTION_PARAM :
color = 0xff333333;
break;
case MATCHED_TEXT_BACKGROUND:
@@ -272,13 +278,26 @@ public class EditorColorScheme {
break;
case FIELD :
case STATIC_FIELD :
case ENUM :
color = 0xFFF0BE4B;
break;
case PACKAGE_NAME :
color = 0xffF0BE4B;
break;
case DIAGNOSTIC_ERROR :
color = 0xfff44336;
break;
case DIAGNOSTIC_WARNING :
color = 0xffFF9800;
break;
case DIAGNOSTIC_INFO :
color = 0xff4CAF50;
break;
case DIAGNOSTIC_HINT :
color = 0xffffffff;
break;
default:
throw new IllegalArgumentException("Unexpected type:" + type);
color = 0xffffffff;
}
setColor(type, color);
}
@@ -28,9 +28,9 @@ public class SchemeDarcula extends EditorColorScheme {
public void applyDefault() {
super.applyDefault();
setColor(ANNOTATION, 0xffbbb529);
setColor(FUNCTION_NAME, 0xffffffff);
setColor(IDENTIFIER_NAME, 0xffffffff);
setColor(IDENTIFIER_VAR, 0xff9876aa);
setColor(METHOD, 0xffffffff);
setColor(TYPE_NAME, 0xffffffff);
setColor(LOCAL_VARIABLE, 0xff9876aa);
setColor(LITERAL, 0xff6a8759);
setColor(OPERATOR, 0xffffffff);
setColor(COMMENT, 0xff808080);
@@ -28,9 +28,9 @@ public final class SchemeEclipse extends EditorColorScheme {
public void applyDefault() {
super.applyDefault();
setColor(ANNOTATION, 0xff646464);
setColor(FUNCTION_NAME, 0xff000000);
setColor(IDENTIFIER_NAME, 0xff000000);
setColor(IDENTIFIER_VAR, 0xffb8633e);
setColor(METHOD, 0xff000000);
setColor(TYPE_NAME, 0xff000000);
setColor(LOCAL_VARIABLE, 0xffb8633e);
setColor(LITERAL, 0xff2a00ff);
setColor(OPERATOR, 0xff3a0000);
setColor(COMMENT, 0xff3f7f5f);
@@ -28,9 +28,9 @@ public final class SchemeGitHub extends EditorColorScheme {
public void applyDefault() {
super.applyDefault();
setColor(ANNOTATION, 0xff6f42c1);
setColor(FUNCTION_NAME, 0xff24292e);
setColor(IDENTIFIER_NAME, 0xff24292e);
setColor(IDENTIFIER_VAR, 0xff24292e);
setColor(METHOD, 0xff24292e);
setColor(TYPE_NAME, 0xff24292e);
setColor(LOCAL_VARIABLE, 0xff24292e);
setColor(LITERAL, 0xff032f62);
setColor(OPERATOR, 0xff005cc5);
setColor(COMMENT, 0xff6a737d);
@@ -28,9 +28,9 @@ public final class SchemeNotepadXX extends EditorColorScheme {
public void applyDefault() {
super.applyDefault();
setColor(ANNOTATION, 0xff0000ff);
setColor(FUNCTION_NAME, 0xff000000);
setColor(IDENTIFIER_NAME, 0xff000000);
setColor(IDENTIFIER_VAR, 0xff000000);
setColor(METHOD, 0xff000000);
setColor(TYPE_NAME, 0xff000000);
setColor(LOCAL_VARIABLE, 0xff000000);
setColor(LITERAL, 0xff808080);
setColor(OPERATOR, 0xff0000ff);
setColor(COMMENT, 0xff008000);
@@ -28,9 +28,9 @@ public class SchemeVS2019 extends EditorColorScheme {
public void applyDefault() {
super.applyDefault();
setColor(ANNOTATION, 0xff4ec9b0);
setColor(FUNCTION_NAME, 0xffdcdcdc);
setColor(IDENTIFIER_NAME, 0xff4ec9b0);
setColor(IDENTIFIER_VAR, 0xffdcdcaa);
setColor(METHOD, 0xff00BCD4);
setColor(TYPE_NAME, 0xff4ec9b0);
setColor(LOCAL_VARIABLE, 0xffdcdcaa);
setColor(LITERAL, 0xffd69d85);
setColor(OPERATOR, 0xffdcdcdc);
setColor(COMMENT, 0xff57a64a);
Binary file not shown.
@@ -294,6 +294,21 @@
android:id="@+id/diagListContainer"/>
</LinearLayout>
<TextView
android:id="@+id/symbolText"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textColor="@color/primaryTextColor"
android:textSize="14sp"
android:singleLine="true"
android:background="@color/content_background"
android:clickable="false"
android:focusable="false"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_view"
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
<com.itsaky.androidide.views.TooltipLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/primaryLightColor">
android:background="@android:color/transparent"
android:paddingBottom="8dp">
<RelativeLayout
android:layout_width="match_parent"
@@ -65,5 +66,4 @@
android:textSize="11sp"
android:textIsSelectable="true"/>
</LinearLayout>
</com.itsaky.androidide.views.TooltipLayout>
+2 -2
View File
@@ -93,11 +93,11 @@
android:id="@+id/menuEditor_runStopDaemons"
android:title="@string/stop_gradle_daemons"
app:showAsAction="never"/>
<item
<!--<item
android:icon="@drawable/ic_recreate"
android:id="@+id/menuEditor_runRecreate"
android:title="@string/recreate_completion_services"
app:showAsAction="never"/>
app:showAsAction="never"/>-->
</menu>
</item>
<item
+1
View File
@@ -13,6 +13,7 @@
<color name="secondaryTextColor_lighter">#f0ffffff</color>
<color name="color_toast_background">#90424242</color>
<color name="primaryIconColor">#ffffff</color>
<color name="primaryIconColor_disabled">#4dffffff</color>
<color name="secondaryIconColor">#9f9f9f</color>
<color name="completionList_background">#373737</color>
<color name="completionList_backgroundSelected">#505050</color>
+7 -7
View File
@@ -8,10 +8,10 @@
<item name="android:textColorSecondary">@color/secondaryTextColor</item>
<item name="colorControlNormal">@color/secondaryColor</item>
<item name="colorControlHighlight">@color/rippleHighlightColor</item>
<item name="android:fontFamily">@font/quicksand</item>
<item name="android:fontFamily">@font/josefin_sans</item>
<item name="windowActionModeOverlay">true</item>
<item name="windowActionBarOverlay">true</item>
<item name="fontFamily">@font/quicksand</item>
<item name="fontFamily">@font/josefin_sans</item>
<item name="shapeAppearanceLargeComponent">@style/AppTheme.ShapeOverlay.Large</item>
<item name="android:windowBackground">@color/content_background</item>
</style>
@@ -57,26 +57,26 @@
<style name="MaterialDialog.Title.Text" parent="@style/MaterialAlertDialog.MaterialComponents.Title.Text">
<item name="android:textColor">@color/primaryTextColor</item>
<item name="android:textStyle">bold</item>
<item name="fontFamily">@font/quicksand</item>
<item name="fontFamily">@font/josefin_sans</item>
</style>
<style name="MaterialDialog.Body.Text" parent="@style/MaterialAlertDialog.MaterialComponents.Body.Text">
<item name="android:textColor">@color/primaryTextColor</item>
<item name="fontFamily">@font/quicksand</item>
<item name="fontFamily">@font/josefin_sans</item>
</style>
<style name="MaterialAlertDialog.PositiveButtonStyle" parent="@style/Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">@color/secondaryColor</item>
<item name="backgroundTint">@android:color/transparent</item>
<item name="fontFamily">@font/quicksand</item>
<item name="fontFamily">@font/josefin_sans</item>
</style>
<style name="MaterialAlertDialog.NegativeButtonStyle" parent="@style/Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">@color/secondaryColor</item>
<item name="backgroundTint">@android:color/transparent</item>
<item name="fontFamily">@font/quicksand</item>
<item name="fontFamily">@font/josefin_sans</item>
</style>
<style name="MaterialAlertDialog.NeutralButtonStyle" parent="@style/Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">@color/secondaryColor</item>
<item name="backgroundTint">@android:color/transparent</item>
<item name="fontFamily">@font/quicksand</item>
<item name="fontFamily">@font/josefin_sans</item>
</style>
<style name="AppTheme.FilePicker" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">@color/primaryColor</item>
+1 -1
View File
@@ -8,7 +8,7 @@ buildscript {
buildTools = "30.0.2"
minSdk = 21
targetSdk = 28
versionCode = 102210625
versionCode = 102210805
versionName = "1.0.2-alpha"
packageName = "com.itsaky.androidide"
}
@@ -1,5 +1,8 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class CancelParams {
@SerializedName("id")
public int id;
}
@@ -1,11 +1,23 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class CodeAction {
public String title, kind;
@SerializedName("title")
public String title;
@SerializedName("kind")
public String kind;
@SerializedName("diagnostics")
public List<Diagnostic> diagnostics;
@SerializedName("edit")
public WorkspaceEdit edit;
@SerializedName("command")
public Command command;
public static CodeAction NONE;
}
@@ -1,9 +1,13 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
public class CodeActionContext {
@SerializedName("diagnostics")
public List<Diagnostic> diagnostics = new ArrayList<>();
@SerializedName("only")
public List<String> only;
}
@@ -1,7 +1,14 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class CodeActionParams {
@SerializedName("textDocument")
public TextDocumentIdentifier textDocument;
@SerializedName("range")
public Range range;
@SerializedName("context")
public CodeActionContext context = new CodeActionContext();
}
@@ -1,10 +1,16 @@
package com.itsaky.lsp;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
public class CodeLens {
@SerializedName("range")
public Range range;
@SerializedName("command")
public Command command;
@SerializedName("data")
public JsonElement data;
public CodeLens() {}
@@ -1,6 +1,9 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class CodeLensParams {
@SerializedName("textDocument")
public TextDocumentIdentifier textDocument;
public CodeLensParams() {}
@@ -1,9 +1,17 @@
package com.itsaky.lsp;
import com.google.gson.JsonArray;
import com.google.gson.annotations.SerializedName;
public class Command {
public String title, command;
@SerializedName("title")
public String title;
@SerializedName("command")
public String command;
@SerializedName("arguments")
public JsonArray arguments;
public Command() {}
@@ -1,19 +1,52 @@
package com.itsaky.lsp;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class CompletionItem {
@SerializedName("label")
public String label;
@SerializedName("kind")
public int kind;
@SerializedName("detail")
public String detail;
@SerializedName("documentation")
public MarkupContent documentation;
public Boolean deprecated, preselect;
public String sortText, filterText, insertText;
@SerializedName("deprecated")
public Boolean deprecated;
@SerializedName("preselect")
public Boolean preselect;
@SerializedName("sortText")
public String sortText;
@SerializedName("filterText")
public String filterText;
@SerializedName("insertText")
public String insertText;
@SerializedName("insertTextFormat")
public Integer insertTextFormat;
@SerializedName("textEdit")
public TextEdit textEdit;
@SerializedName("additionalTextEdits")
public List<TextEdit> additionalTextEdits;
@SerializedName("commitCharacters")
public List<Character> commitCharacters;
@SerializedName("command")
public Command command;
@SerializedName("data")
public JsonElement data;
}
@@ -1,12 +1,16 @@
package com.itsaky.lsp;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class CompletionList {
@SerializedName("isIncomplete")
public boolean isIncomplete;
@SerializedName("items")
public List<CompletionItem> items;
public CompletionList() {
@@ -1,10 +1,24 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class Diagnostic {
@SerializedName("range")
public Range range;
@SerializedName("severity")
public Integer severity;
public String code, source, message;
@SerializedName("code")
public String code;
@SerializedName("source")
public String source;
@SerializedName("message")
public String message;
@SerializedName("tags")
public List<Integer> tags;
}
@@ -1,7 +1,9 @@
package com.itsaky.lsp;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
public class DidChangeConfigurationParams {
@SerializedName("settings")
public JsonElement settings;
}
@@ -1,9 +1,13 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
public class DidChangeTextDocumentParams {
@SerializedName("textDocument")
public VersionedTextDocumentIdentifier textDocument = new VersionedTextDocumentIdentifier();
@SerializedName("contentChanges")
public List<TextDocumentContentChangeEvent> contentChanges = new ArrayList<>();
}
@@ -1,7 +1,15 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.util.List;
import java.util.ArrayList;
public class DidChangeWatchedFilesParams {
public List<FileEvent> changes;
@SerializedName("changes")
public List<FileEvent> changes = new ArrayList<>();
public DidChangeWatchedFilesParams() {
changes = new ArrayList<>();
}
}
@@ -1,5 +1,8 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class DidChangeWorkspaceFoldersParams {
@SerializedName("event")
public WorkspaceFoldersChangeEvent event;
}
@@ -1,5 +1,9 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class DidCloseTextDocumentParams {
@SerializedName("textDocument")
public TextDocumentIdentifier textDocument = new TextDocumentIdentifier();
}
@@ -1,5 +1,8 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class DidOpenTextDocument {
@SerializedName("textDocument")
public TextDocumentItem textDocument;
}
@@ -1,6 +1,10 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class DidOpenTextDocumentParams {
@SerializedName("textDocument")
public TextDocumentItem textDocument = new TextDocumentItem();
public DidOpenTextDocumentParams() {}
@@ -1,6 +1,12 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class DidSaveTextDocumentParams {
@SerializedName("textDocument")
public TextDocumentIdentifier textDocument;
@SerializedName("text")
public String text;
}
@@ -1,6 +1,12 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class DocumentFormattingParams {
@SerializedName("textDocument")
public TextDocumentIdentifier textDocument;
@SerializedName("options")
public FormattingOptions options;
}
@@ -1,6 +1,12 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class DocumentHighlight {
@SerializedName("range")
public Range range;
@SerializedName("kind")
public int kind;
}
@@ -1,9 +1,16 @@
package com.itsaky.lsp;
import com.google.gson.JsonArray;
import com.google.gson.annotations.SerializedName;
public class DocumentLink {
@SerializedName("range")
public Range range;
@SerializedName("target")
public String target;
@SerializedName("data")
public JsonArray data;
}
@@ -1,6 +1,10 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class DocumentLinkParams {
@SerializedName("textDocument")
public TextDocumentIdentifier textDocument;
public DocumentLinkParams() {}
@@ -1,11 +1,27 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class DocumentSymbol {
public String name, detail;
@SerializedName("name")
public String name;
@SerializedName("detail")
public String detail;
@SerializedName("kind")
public int kind;
@SerializedName("deprecated")
public boolean deprecated;
public Range range, selectionRange;
@SerializedName("range")
public Range range;
@SerializedName("selectionRange")
public Range selectionRange;
@SerializedName("children")
public List<DocumentSymbol> children;
}
@@ -1,6 +1,10 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class DocumentSymbolParams {
@SerializedName("textDocument")
public TextDocumentIdentifier textDocument;
public DocumentSymbolParams() {}
@@ -1,9 +1,18 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.net.URI;
public class FileEvent {
@SerializedName("uri")
public URI uri;
// FileChangeType
@SerializedName("type")
public int type;
public FileEvent(URI uri, int type) {
this.uri = uri;
this.type = type;
}
}
@@ -1,8 +1,22 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class FoldingRange {
public int startLine, startCharacter, endLine, endCharacter;
public String kind; // FoldingRangeKind
@SerializedName("startLine")
public int startLine;
@SerializedName("startCharacter")
public int startCharacter;
@SerializedName("endLine")
public int endLine;
@SerializedName("endCharacter")
public int endCharacter;
@SerializedName("kind")
public String kind;
public FoldingRange() {}
@@ -1,5 +1,9 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class FoldingRangeParams {
@SerializedName("textDocument")
public TextDocumentIdentifier textDocument;
}
@@ -1,7 +1,13 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class FormattingOptions {
@SerializedName("tabSize")
public int tabSize;
@SerializedName("insertSpaces")
public boolean insertSpaces;
public FormattingOptions(){}
@@ -1,9 +1,13 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class Hover {
@SerializedName("contents")
public List<MarkedString> contents;
@SerializedName("range")
public Range range;
public Hover() {}
@@ -1,14 +1,30 @@
package com.itsaky.lsp;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
import java.net.URI;
import java.util.List;
import java.util.Set;
public class InitializeParams {
@SerializedName("processId")
public int processId;
@SerializedName("rootPath")
public String rootPath;
@SerializedName("rootUri")
public URI rootUri;
@SerializedName("roots")
public Set<URI> roots;
@SerializedName("initializationOptions")
public JsonElement initializationOptions;
@SerializedName("trace")
public String trace;
@SerializedName("workspaceFolders")
public List<WorkspaceFolder> workspaceFolders;
}
@@ -1,8 +1,11 @@
package com.itsaky.lsp;
import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName;
public class InitializeResult {
@SerializedName("capabilities")
public JsonObject capabilities;
public InitializeResult() {}
@@ -1,22 +1,71 @@
package com.itsaky.lsp;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
/**
* A class which stores the syntax highlighting colors obtained from JLS
*/
public class JavaColors {
@SerializedName("uri")
public URI uri;
@SerializedName("packages")
public List<Range> packages;
@SerializedName("enumTypes")
public List<Range> enumTypes;
@SerializedName("classNames")
public List<Range> classNames;
@SerializedName("annotationTypes")
public List<Range> annotationTypes;
@SerializedName("interfaces")
public List<Range> interfaces;
@SerializedName("enums")
public List<Range> enums;
@SerializedName("statics")
public List<Range> statics;
@SerializedName("fields")
public List<Range> fields;
@SerializedName("classNames")
public List<Range> classNames;
@SerializedName("parameters")
public List<Range> parameters;
@SerializedName("packages")
public List<Range> packages;
@SerializedName("locals")
public List<Range> locals;
@SerializedName("exceptionParams")
public List<Range> exceptionParams;
@SerializedName("methods")
public List<Range> methods;
@SerializedName("constructors")
public List<Range> constructors;
@SerializedName("staticInits")
public List<Range> staticInits;
@SerializedName("instanceInits")
public List<Range> instanceInits;
@SerializedName("typeParams")
public List<Range> typeParams;
@SerializedName("resourceVariables")
public List<Range> resourceVariables;
@Override
public String toString() {
return new GsonBuilder().setPrettyPrinting().create().toJson(this);
}
}
@@ -1,7 +1,12 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class JavaReportProgressParams {
@SerializedName("message")
private String message;
@SerializedName("increment")
private int increment = -1;
public JavaReportProgressParams() {}
@@ -1,6 +1,10 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class JavaStartProgressParams {
@SerializedName("message")
private String message;
public JavaStartProgressParams() {}
@@ -1,6 +1,7 @@
package com.itsaky.lsp;
import com.google.gson.JsonElement;
import java.io.File;
public interface LanguageClient {
void javaProgressStart(JavaStartProgressParams params);
@@ -8,6 +9,7 @@ public interface LanguageClient {
void javaProgressEnd();
void publishDiagnostics(PublishDiagnosticsParams params);
void signatureHelp(SignatureHelp signature, File file);
void javaColors(JavaColors colors);
void showMessage(ShowMessageParams params);
@@ -1,9 +1,13 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.net.URI;
public class Location {
@SerializedName("uri")
public URI uri;
@SerializedName("range")
public Range range;
public Location() {}
@@ -2,13 +2,18 @@ package com.itsaky.lsp;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
@JsonAdapter(MarkedString.Adapter.class)
public class MarkedString {
public String language, value;
@SerializedName("language")
public String language;
@SerializedName("value")
public String value;
public MarkedString() {}
@@ -1,7 +1,13 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class MarkupContent {
public String kind, value;
@SerializedName("kind")
public String kind;
@SerializedName("value")
public String value;
public MarkupContent() {}
@@ -1,10 +1,18 @@
package com.itsaky.lsp;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
public class Message {
@SerializedName("jsonrpc")
public String jsonrpc;
@SerializedName("id")
public Integer id;
@SerializedName("method")
public String method;
@SerializedName("params")
public JsonElement params;
}
@@ -1,8 +1,13 @@
package com.itsaky.lsp;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
public class NotificationMessage {
@SerializedName("method")
public String method;
@SerializedName("params")
public JsonElement params;
}
@@ -1,6 +1,11 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class ParameterInformation {
@SerializedName("label")
public String label;
@SerializedName("documentation")
public MarkupContent documentation;
}
@@ -1,9 +1,15 @@
package com.itsaky.lsp;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
public class Position {
public int line, character;
@SerializedName("line")
public int line;
@SerializedName("character")
public int character;
public Position() {}
@@ -1,11 +1,16 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
public class PublishDiagnosticsParams {
@SerializedName("uri")
public URI uri;
@SerializedName("diagnostics")
public List<Diagnostic> diagnostics;
public PublishDiagnosticsParams() {
+6 -1
View File
@@ -1,9 +1,14 @@
package com.itsaky.lsp;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
public class Range {
public Position start, end;
@SerializedName("start")
public Position start;
@SerializedName("end")
public Position end;
public Range() {}
@@ -1,5 +1,9 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class ReferenceContext {
@SerializedName("includeDeclaration")
public boolean includeDeclaration;
}
@@ -1,5 +1,9 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class ReferenceParams extends TextDocumentPositionParams {
@SerializedName("context")
public ReferenceContext context;
}
@@ -1,8 +1,16 @@
package com.itsaky.lsp;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
public class RegistrationParams {
public String id, method;
@SerializedName("id")
public String id;
@SerializedName("method")
public String method;
@SerializedName("registerOptions")
public JsonElement registerOptions;
}
@@ -1,7 +1,16 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class RenameParams {
@SerializedName("textDocument")
public TextDocumentIdentifier textDocument;
@SerializedName("position")
public Position position;
@SerializedName("newName")
public String newName;
}
@@ -1,6 +1,12 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class RenameResponse {
@SerializedName("range")
public Range range;
@SerializedName("placeholder")
public String placeholder;
}
@@ -1,8 +1,16 @@
package com.itsaky.lsp;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
public class RequestMessage {
public String id, method;
@SerializedName("id")
public String id;
@SerializedName("method")
public String method;
@SerializedName("params")
public JsonElement params;
}
@@ -1,8 +1,16 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class ResponseError {
@SerializedName("code")
public int code;
@SerializedName("message")
public String message;
@SerializedName("data")
public Object data;
public ResponseError() {}
@@ -1,6 +1,12 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class ShowMessageParams {
@SerializedName("type")
public int type;
@SerializedName("message")
public String message;
}
@@ -1,10 +1,17 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class SignatureHelp {
@SerializedName("signatures")
public List<SignatureInformation> signatures;
public Integer activeSignature, activeParameter;
@SerializedName("activeSignature")
public Integer activeSignature;
@SerializedName("activeParameter")
public Integer activeParameter;
public SignatureHelp() {}
@@ -1,10 +1,17 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class SignatureInformation {
@SerializedName("label")
public String label;
@SerializedName("documentation")
public MarkupContent documentation;
@SerializedName("parameters")
public List<ParameterInformation> parameters;
public SignatureInformation() {}
@@ -1,9 +1,21 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class SymbolInformation {
@SerializedName("name")
public String name;
@SerializedName("kind")
public int kind;
@SerializedName("deprecated")
public boolean deprecated;
@SerializedName("location")
public Location location;
@SerializedName("containerName")
public String containerName;
}
@@ -1,7 +1,14 @@
package com.itsaky.lsp;
import com.google.gson.annotations.SerializedName;
public class TextDocumentContentChangeEvent {
@SerializedName("range")
public Range range;
@SerializedName("rangeLength")
public Integer rangeLength;
@SerializedName("text")
public String text;
}

Some files were not shown because too many files have changed in this diff Show More