Reformatted code

This commit is contained in:
Akash Yadav
2022-04-17 21:10:16 +05:30
parent af32767b3d
commit e058469e0b
2 changed files with 752 additions and 287 deletions
+493
View File
@@ -4,11 +4,33 @@
<option name="SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER" value="true" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" alias="false" withSubpackages="true" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
<package name="io.ktor" alias="false" withSubpackages="true" />
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="IMPORT_NESTED_CLASSES" value="true" />
<option name="ALLOW_TRAILING_COMMA" value="true" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="Groovy">
<option name="SPACE_WITHIN_BRACES" value="false" />
<option name="SPACE_BEFORE_METHOD_CALL_PARENTHESES" value="true" />
<option name="SPACE_BEFORE_METHOD_PARENTHESES" value="true" />
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="false" />
<option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="false" />
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="false" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<indentOptions>
<option name="KEEP_INDENTS_ON_EMPTY_LINES" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="SPACE_BEFORE_METHOD_CALL_PARENTHESES" value="true" />
<option name="SPACE_BEFORE_METHOD_PARENTHESES" value="true" />
@@ -18,6 +40,477 @@
<indentOptions>
<option name="KEEP_INDENTS_ON_EMPTY_LINES" value="true" />
</indentOptions>
<arrangement>
<groups>
<group>
<type>GETTERS_AND_SETTERS</type>
<order>KEEP</order>
</group>
<group>
<type>OVERRIDDEN_METHODS</type>
<order>KEEP</order>
</group>
<group>
<type>DEPENDENT_METHODS</type>
<order>BREADTH_FIRST</order>
</group>
</groups>
<rules>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PUBLIC>true</PUBLIC>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PROTECTED>true</PROTECTED>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PRIVATE>true</PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PUBLIC>true</PUBLIC>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PROTECTED>true</PROTECTED>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PRIVATE>true</PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<INITIALIZER_BLOCK>true</INITIALIZER_BLOCK>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PUBLIC>true</PUBLIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PROTECTED>true</PROTECTED>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PRIVATE>true</PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PUBLIC>true</PUBLIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PROTECTED>true</PROTECTED>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PRIVATE>true</PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<FIELD>true</FIELD>
</match>
</rule>
</section>
<section>
<rule>
<match>
<INITIALIZER_BLOCK>true</INITIALIZER_BLOCK>
</match>
</rule>
</section>
<section>
<rule>
<match>
<CONSTRUCTOR>true</CONSTRUCTOR>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD>true</METHOD>
<PUBLIC>true</PUBLIC>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD>true</METHOD>
<PROTECTED>true</PROTECTED>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD>true</METHOD>
<PRIVATE>true</PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD>true</METHOD>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD>true</METHOD>
<PUBLIC>true</PUBLIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD>true</METHOD>
<PROTECTED>true</PROTECTED>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD>true</METHOD>
<PRIVATE>true</PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD>true</METHOD>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<METHOD>true</METHOD>
</match>
</rule>
</section>
<section>
<rule>
<match>
<ENUM>true</ENUM>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<PUBLIC>true</PUBLIC>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<PROTECTED>true</PROTECTED>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<PRIVATE>true</PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<PUBLIC>true</PUBLIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<PROTECTED>true</PROTECTED>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<PRIVATE>true</PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<CLASS>true</CLASS>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<INTERFACE>true</INTERFACE>
<PUBLIC>true</PUBLIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<INTERFACE>true</INTERFACE>
<PROTECTED>true</PROTECTED>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<INTERFACE>true</INTERFACE>
<PRIVATE>true</PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<INTERFACE>true</INTERFACE>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<INTERFACE>true</INTERFACE>
</match>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
@@ -106,6 +106,47 @@ public class IDEEditor extends CodeEditor {
setInputType(createInputFlags());
}
private void handleSelectionChange(
@NonNull SelectionChangeEvent event, Unsubscribe unsubscribe) {
if (event.isSelected() || !(getEditorLanguage() instanceof IDELanguage)) {
// do not show diagnostics when text is selected
// or if we cannot get diagnostics
return;
}
final var diagnostics = ((IDELanguage) getEditorLanguage()).getDiagnostics();
final var line = event.getLeft().line;
final var column = event.getLeft().column;
// diagnostics are expected to be sorted, so, we do a binary search
final var diagnostic = binarySearchDiagnostic(diagnostics, line, column);
getDiagnosticWindow().showDiagnostic(diagnostic);
}
/**
* Notify the language server that the content of this file has been changed.
*
* @param event The content change event.
*/
private void handleContentChange(ContentChangeEvent event, Unsubscribe unsubscribe) {
if (getContext() instanceof Activity) {
((Activity) getContext()).invalidateOptionsMenu();
}
if (getFile() == null || mLanguageServer == null) {
return;
}
final var documentHandler = mLanguageServer.getDocumentHandler();
final var file = getFile().toPath();
if (documentHandler.accepts(file)) {
documentHandler.onContentChange(
new DocumentChangeEvent(file, getText(), mFileVersion + 1));
}
checkForSignatureHelp(event);
}
public static int createInputFlags() {
var flags =
EditorInfo.TYPE_CLASS_TEXT
@@ -120,100 +161,18 @@ public class IDEEditor extends CodeEditor {
return flags;
}
public void analyze() {
if (mLanguageServer != null
&& getFile() != null
&& getEditorLanguage() instanceof IDELanguage) {
CompletableFuture.supplyAsync(() -> mLanguageServer.analyze(getFile().toPath()))
.whenComplete(
(diagnostics, throwable) -> {
final var lang = (IDELanguage) getEditorLanguage();
final var analyzer = lang.getAnalyzeManager();
if (analyzer instanceof IAnalyzeManager) {
((IAnalyzeManager) analyzer).updateDiagnostics(diagnostics);
}
analyzer.rerun();
});
}
@Nullable
private DiagnosticItem binarySearchDiagnostic(
@NonNull List<DiagnosticItem> diagnostics, int line, int column) {
return DiagnosticUtil.binarySearchDiagnostic(diagnostics, line, column);
}
/**
* Checks if the given range is valid for this editor's text.
*
* @param range The range to check.
* @return <code>true</code> if valid, <code>false</code> otherwise.
*/
public boolean isValidRange(final Range range) {
if (range == null) {
return false;
private DiagnosticWindow getDiagnosticWindow() {
if (mDiagnosticWindow == null) {
mDiagnosticWindow = new DiagnosticWindow(this);
}
final var start = range.getStart();
final var end = range.getEnd();
return isValidPosition(start)
&& isValidPosition(end)
&& start.compareTo(end) < 0; // make sure start position is before end position
}
/**
* Checks if the given position is valid for this editor's text.
*
* @param position The position to check.
* @return <code>true</code> if valid, <code>false</code> otherwise.
*/
public boolean isValidPosition(final Position position) {
if (position == null) {
return false;
}
return isValidLine(position.getLine())
&& isValidColumn(position.getLine(), position.getColumn());
}
/**
* Checks if the given line is valid for this editor's text.
*
* @param line The line to check.
* @return <code>true</code> if valid, <code>false</code> otherwise.
*/
public boolean isValidLine(int line) {
return line >= 0 && line < getText().getLineCount();
}
/**
* Checks if the given column is valid for this editor's text.
*
* @param line The line of the column to check.
* @param column The column to check.
* @return <code>true</code> if valid, <code>false</code> otherwise.
*/
public boolean isValidColumn(int line, int column) {
return column >= 0 && column < getText().getColumnCount(line);
}
/**
* Set selection to the given range.
*
* @param range The range to select.
*/
public void setSelection(@NonNull Range range) {
if (isValidRange(range)) {
setSelectionRegion(
range.getStart().getLine(),
range.getStart().getColumn(),
range.getEnd().getLine(),
range.getEnd().getColumn());
}
}
/**
* Set the selection of this editor to the given position.
*
* @param position The position to select.
*/
public void setSelection(@NonNull Position position) {
setSelection(position.getLine(), position.getColumn());
return mDiagnosticWindow;
}
/**
@@ -252,6 +211,104 @@ public class IDEEditor extends CodeEditor {
}
}
public void analyze() {
if (mLanguageServer != null
&& getFile() != null
&& getEditorLanguage() instanceof IDELanguage) {
CompletableFuture.supplyAsync(() -> mLanguageServer.analyze(getFile().toPath()))
.whenComplete(
(diagnostics, throwable) -> {
final var lang = (IDELanguage) getEditorLanguage();
final var analyzer = lang.getAnalyzeManager();
if (analyzer instanceof IAnalyzeManager) {
((IAnalyzeManager) analyzer).updateDiagnostics(diagnostics);
}
analyzer.rerun();
});
}
}
/**
* Checks if the content change event should trigger signature help. Signature help trigger
* characters are :
*
* <ul>
* <li><code>'('</code> (parentheses)
* <li><code>','</code> (comma)
* </ul>
*
* @param event The content change event.
*/
private void checkForSignatureHelp(@NonNull ContentChangeEvent event) {
if (event.getAction() != ContentChangeEvent.ACTION_INSERT
|| event.getChangedText().length() != 1) {
return;
}
final var ch = event.getChangedText().charAt(0);
if (ch == '(' || ch == ',') {
signatureHelp();
}
}
/**
* If any language server is set, requests signature help at the cursor's position. On a valid
* response, shows the signature help in a popup window.
*/
@SuppressWarnings("unused") // accessed using reflection in CompletionItem class
public void signatureHelp() {
if (mLanguageServer != null && getFile() != null) {
final CompletableFuture<SignatureHelp> future =
CompletableFuture.supplyAsync(
() ->
mLanguageServer.signatureHelp(
new SignatureHelpParams(
getFile().toPath(),
new Position(
getCursor().getLeftLine(),
getCursor().getLeftColumn()))));
future.whenComplete(
(help, error) -> {
if (help == null
|| mLanguageClient == null
|| future.isCancelled()
|| future.isCompletedExceptionally()) {
LOG.error("An error occurred while finding signature help", error);
return;
}
ThreadUtils.runOnUiThread(() -> showSignatureHelp(help));
});
}
}
/**
* Shows the given signature help in the editor.
*
* @param help The signature help data to show.
*/
public void showSignatureHelp(SignatureHelp help) {
getSignatureHelpWindow().setupAndDisplay(help);
}
private SignatureHelpWindow getSignatureHelpWindow() {
if (mSignatureHelpWindow == null) {
mSignatureHelpWindow = new SignatureHelpWindow(this);
}
return mSignatureHelpWindow;
}
/**
* Set the selection of this editor to the given position.
*
* @param position The position to select.
*/
public void setSelection(@NonNull Position position) {
setSelection(position.getLine(), position.getColumn());
}
/**
* Set the language server that this editor will connect with. If the language client is not
* set, it'll be set to {@link IDELanguageClientImpl}.
@@ -451,6 +508,85 @@ public class IDEEditor extends CodeEditor {
});
}
/**
* Set selection to the given range.
*
* @param range The range to select.
*/
public void setSelection(@NonNull Range range) {
if (isValidRange(range)) {
setSelectionRegion(
range.getStart().getLine(),
range.getStart().getColumn(),
range.getEnd().getLine(),
range.getEnd().getColumn());
}
}
/**
* Dismisses the given dialog on the UI thread.
*
* @param dialog The dialog to dismiss.
*/
private void dismissOnUiThread(@NonNull final Dialog dialog) {
ThreadUtils.runOnUiThread(dialog::dismiss);
}
/**
* Checks if the given range is valid for this editor's text.
*
* @param range The range to check.
* @return <code>true</code> if valid, <code>false</code> otherwise.
*/
public boolean isValidRange(final Range range) {
if (range == null) {
return false;
}
final var start = range.getStart();
final var end = range.getEnd();
return isValidPosition(start)
&& isValidPosition(end)
&& start.compareTo(end) < 0; // make sure start position is before end position
}
/**
* Checks if the given position is valid for this editor's text.
*
* @param position The position to check.
* @return <code>true</code> if valid, <code>false</code> otherwise.
*/
public boolean isValidPosition(final Position position) {
if (position == null) {
return false;
}
return isValidLine(position.getLine())
&& isValidColumn(position.getLine(), position.getColumn());
}
/**
* Checks if the given line is valid for this editor's text.
*
* @param line The line to check.
* @return <code>true</code> if valid, <code>false</code> otherwise.
*/
public boolean isValidLine(int line) {
return line >= 0 && line < getText().getLineCount();
}
/**
* Checks if the given column is valid for this editor's text.
*
* @param line The line of the column to check.
* @param column The column to check.
* @return <code>true</code> if valid, <code>false</code> otherwise.
*/
public boolean isValidColumn(int line, int column) {
return column >= 0 && column < getText().getColumnCount(line);
}
/**
* If any language server instance is set, finds the references to of the token at the current
* cursor position.
@@ -533,56 +669,6 @@ public class IDEEditor extends CodeEditor {
});
}
/**
* If any language server is set, requests signature help at the cursor's position. On a valid
* response, shows the signature help in a popup window.
*/
@SuppressWarnings("unused") // accessed using reflection in CompletionItem class
public void signatureHelp() {
if (mLanguageServer != null && getFile() != null) {
final CompletableFuture<SignatureHelp> future =
CompletableFuture.supplyAsync(
() ->
mLanguageServer.signatureHelp(
new SignatureHelpParams(
getFile().toPath(),
new Position(
getCursor().getLeftLine(),
getCursor().getLeftColumn()))));
future.whenComplete(
(help, error) -> {
if (help == null
|| mLanguageClient == null
|| future.isCancelled()
|| future.isCompletedExceptionally()) {
LOG.error("An error occurred while finding signature help", error);
return;
}
ThreadUtils.runOnUiThread(() -> showSignatureHelp(help));
});
}
}
/**
* Shows the given signature help in the editor.
*
* @param help The signature help data to show.
*/
public void showSignatureHelp(SignatureHelp help) {
getSignatureHelpWindow().setupAndDisplay(help);
}
/**
* Dismisses the given dialog on the UI thread.
*
* @param dialog The dialog to dismiss.
*/
private void dismissOnUiThread(@NonNull final Dialog dialog) {
ThreadUtils.runOnUiThread(dialog::dismiss);
}
/** If any language server is set, notify the server that the file in this editor was saved. */
public void didSave() {
if (mLanguageServer != null && getFile() != null) {
@@ -611,6 +697,23 @@ public class IDEEditor extends CodeEditor {
ensureWindowsDismissed();
}
/** Ensures that all the windows are dismissed. */
public void ensureWindowsDismissed() {
if (getDiagnosticWindow().isShowing()) {
getDiagnosticWindow().dismiss();
}
if (getSignatureHelpWindow().isShowing()) {
getSignatureHelpWindow().dismiss();
}
if (mActionsPopup != null) {
if (mActionsPopup.isShowing()) {
mActionsPopup.dismiss();
}
}
}
public void onEditorSelected() {
if (getFile() == null) {
return;
@@ -622,17 +725,6 @@ public class IDEEditor extends CodeEditor {
}
}
/**
* Tells the language client to perform the given code action item.
*
* @param action The action to perform.
*/
public void performCodeAction(CodeActionItem action) {
if (mLanguageClient != null) {
mLanguageClient.performCodeAction(this, action);
}
}
@SuppressWarnings("unused")
public void executeCommand(Command command) {
if (command == null) {
@@ -693,16 +785,6 @@ public class IDEEditor extends CodeEditor {
}));
}
/**
* Get the cursor's position in the form of {@link Position}.
*
* @return The {@link Position} of the cursor.
*/
@SuppressWarnings("unused")
public Position getCursorAsLSPPosition() {
return new Position(getCursor().getLeftLine(), getCursor().getLeftColumn());
}
/**
* Get the cursor's selection range in the form of {@link Range}.
*
@@ -715,6 +797,16 @@ public class IDEEditor extends CodeEditor {
return new Range(start, end);
}
/**
* Get the cursor's position in the form of {@link Position}.
*
* @return The {@link Position} of the cursor.
*/
@SuppressWarnings("unused")
public Position getCursorAsLSPPosition() {
return new Position(getCursor().getLeftLine(), getCursor().getLeftColumn());
}
/**
* Validates the range if it is invalid and returns a valid range.
*
@@ -765,135 +857,15 @@ public class IDEEditor extends CodeEditor {
return new Range(start, end);
}
private void notifyNoCodeActions() {
ThreadUtils.runOnUiThread(
() -> StudioApp.getInstance().toast(R.string.msg_no_actions, Toaster.Type.ERROR));
}
/** Ensures that all the windows are dismissed. */
public void ensureWindowsDismissed() {
if (getDiagnosticWindow().isShowing()) {
getDiagnosticWindow().dismiss();
}
if (getSignatureHelpWindow().isShowing()) {
getSignatureHelpWindow().dismiss();
}
if (mActionsPopup != null) {
if (mActionsPopup.isShowing()) {
mActionsPopup.dismiss();
}
}
}
public void showCodeActions(List<CodeActionItem> actions) {
if (actions == null || actions.isEmpty()) {
StudioApp.getInstance()
.toast(getContext().getString(R.string.msg_no_actions), Toaster.Type.ERROR);
return;
}
final var titles = actions.stream().map(CodeActionItem::getTitle).toArray(String[]::new);
final var builder = DialogUtils.newMaterialDialogBuilder(getContext());
builder.setTitle("Select code action...");
builder.setItems(
titles,
(dialog, which) -> {
final var action = actions.get(which);
if (action != null) {
performCodeAction(action);
} else {
LOG.error("Cannot perform code action. Action is null.");
}
});
builder.show();
}
private void handleSelectionChange(
@NonNull SelectionChangeEvent event, Unsubscribe unsubscribe) {
if (event.isSelected() || !(getEditorLanguage() instanceof IDELanguage)) {
// do not show diagnostics when text is selected
// or if we cannot get diagnostics
return;
}
final var diagnostics = ((IDELanguage) getEditorLanguage()).getDiagnostics();
final var line = event.getLeft().line;
final var column = event.getLeft().column;
// diagnostics are expected to be sorted, so, we do a binary search
final var diagnostic = binarySearchDiagnostic(diagnostics, line, column);
getDiagnosticWindow().showDiagnostic(diagnostic);
}
@Nullable
private DiagnosticItem binarySearchDiagnostic(
@NonNull List<DiagnosticItem> diagnostics, int line, int column) {
return DiagnosticUtil.binarySearchDiagnostic(diagnostics, line, column);
}
/**
* Notify the language server that the content of this file has been changed.
* Tells the language client to perform the given code action item.
*
* @param event The content change event.
* @param action The action to perform.
*/
private void handleContentChange(ContentChangeEvent event, Unsubscribe unsubscribe) {
if (getContext() instanceof Activity) {
((Activity) getContext()).invalidateOptionsMenu();
public void performCodeAction(CodeActionItem action) {
if (mLanguageClient != null) {
mLanguageClient.performCodeAction(this, action);
}
if (getFile() == null || mLanguageServer == null) {
return;
}
final var documentHandler = mLanguageServer.getDocumentHandler();
final var file = getFile().toPath();
if (documentHandler.accepts(file)) {
documentHandler.onContentChange(
new DocumentChangeEvent(file, getText(), mFileVersion + 1));
}
checkForSignatureHelp(event);
}
/**
* Checks if the content change event should trigger signature help. Signature help trigger
* characters are :
*
* <ul>
* <li><code>'('</code> (parentheses)
* <li><code>','</code> (comma)
* </ul>
*
* @param event The content change event.
*/
private void checkForSignatureHelp(@NonNull ContentChangeEvent event) {
if (event.getAction() != ContentChangeEvent.ACTION_INSERT
|| event.getChangedText().length() != 1) {
return;
}
final var ch = event.getChangedText().charAt(0);
if (ch == '(' || ch == ',') {
signatureHelp();
}
}
private SignatureHelpWindow getSignatureHelpWindow() {
if (mSignatureHelpWindow == null) {
mSignatureHelpWindow = new SignatureHelpWindow(this);
}
return mSignatureHelpWindow;
}
private DiagnosticWindow getDiagnosticWindow() {
if (mDiagnosticWindow == null) {
mDiagnosticWindow = new DiagnosticWindow(this);
}
return mDiagnosticWindow;
}
}