diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..e7ee2cf8c
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,2 @@
+# Contributing
+You can build AndroidIDE on Android Studio. Building AndroidIDE on AndroidIDE itself is also possible but you might face difficulties doing so. So, Android Studio is recommended.
\ No newline at end of file
diff --git a/README.md b/README.md
index 49d089f51..b6f93405a 100755
--- a/README.md
+++ b/README.md
@@ -1,30 +1,22 @@
-
-
AndroidIDE
+
-
-## Main Features
-- Supports Gradle
-- Comes with OpenJDK 11.0.12
-- Provides auto completion for Java and XML. It also has basic (reserved) completion for Gradle files.
-
-More features will be implemented as we continue to develop this app.
-
-## Features to be implemented
-- [x] Advanced Java Auto Complete
-- [x] Terminal
-- [x] Custom environment variables (for Build & Terminal)
-- [x] SDK Manager (Available via terminal)
-- [x] Gradlew support (with some limitations)
+## Features
+- [x] Gradle support.
+- [x] `JDK 11` and `JDK 17` available for use.
+- [x] Terminal with necessary packages.
+- [x] Custom environment variables (for Build & Terminal).
+- [x] SDK Manager (Available via terminal).
- [x] API information for classes and their members (since, removed, deprecated).
-- [ ] Implement language servers
+- [ ] Language servers
+ - [x] Java
- [ ] XML
- [ ] Kotlin
- [ ] UI Designer
@@ -45,67 +37,19 @@ Git is currently available only in the terminal i.e. no GUI interface for `git`.
- Gradle Wrapper is supported. But, it requires that the project's application module is named 'app'.
- SDK Manager is already included in Android SDK and is accessible in AndroidIDE via its Terminal. But, you cannot use it to install some tools (like NDK) because those tools are not built for Android.
- No official NDK support because we haven't built the NDK for Android.
-- No Android Gradle Plugin versions other than v7.0.2 are supported (due to AAPT2).
The app is still being developed actively. It's in beta stage and may not be stable. if you have any issues using the app, please let us know.
## Issues/suggestions
You should report bugs and suggest features/enhancements [here](https://github.com/itsaky/AndroidIDE/issues).
-Describe the issue/request briefly. Provide steps to reproduce the issue. If you need any help, you should discuss it [here](https://t.me/androidide_discussions).
+Describe the issue/request briefly. Provide steps to reproduce the issue.
-If you open a build related issue, please provide these details:
-- Device model
-- Android Version
-- Full build output with stacktrace.
+If you need any help, you should discuss it [here](https://t.me/androidide_discussions).
-## Screenshots
-| Main Screen | Terminal |
-| ----------- | -------- |
-|
|
|
-
-| Build Output | Java Completion |
-| ------------ | --------------- |
-|
|
|
-
-| XML Completion | Screenshot |
-| -------------- | ---------- |
-| Widgets |
-| Attributes |
-| Attribute Values |
-
-| Gradle Support | File Tree |
-| -------------- | --------- |
-|
|
|
-
-## Posts to help you get started
-- [Installing AndroidIDE](https://telegra.ph/How-to-install-AndroidIDE-09-11)
- - Author: [Marvin Stelter](https://github.com/MarvinStelter)
-- [Create your first project](https://itsaky.github.io/create-your-first-project-in-androidIDE/)
- - Author: [Akash Yadav](https://github.com/itsaky)
-
-## Developers
-This project was initially developed by [Akash Yadav](https://github.com/itsaky) and [Marvin Stelter](https://github.com/MarvinStelter). We appreciate the efforts of anyone who contributes to this project.
+Provide a proper title and a short description for issues.
## Contributing
-You can contribute to AndroidIDE in one of the following ways :
-- Fix bugs
-- Implement new features
-- Report bugs
-- Suggest a change
-- Request a feature
-- Improve the documentation
-
-If you create new source files, please make sure you include the license header in every file.
-
-### Things to take care of
-There are some things that you should take care of while writing related code.
-
-- Layout Inflater adapters
- - [Read the docs](./xml-inflater/src/main/java/com/itsaky/inflater/adapters/README.md) about layout inflater adapters.
-
-### Any other ways to contribute?
-You can also write blog posts or create YouTube videos to help newbies get started.
-If you do and want us to feature it here, open an issue.
+See the [contributing guide](./CONTRIBUTING.md).
## Thanks to
- [Rosemoe](https://github.com/Rosemoe) for the awesome [CodeEditor](https://github.com/Rosemoe/sora-editor)
@@ -135,4 +79,4 @@ You should have received a copy of the GNU General Public License
along with AndroidIDE. If not, see .
```
-Any violations to the license can be reported either by opening an issue or writing a mail to us directly.
+Any violations to the license can be reported either by opening an issue or writing a mail to us directly.
\ No newline at end of file
diff --git a/app/src/main/java/com/itsaky/androidide/EditorActivity.java b/app/src/main/java/com/itsaky/androidide/EditorActivity.java
index d754c54d5..e0a9a25c4 100755
--- a/app/src/main/java/com/itsaky/androidide/EditorActivity.java
+++ b/app/src/main/java/com/itsaky/androidide/EditorActivity.java
@@ -88,7 +88,7 @@ import com.itsaky.androidide.managers.PreferenceManager;
import com.itsaky.androidide.managers.ToolsManager;
import com.itsaky.androidide.models.DiagnosticGroup;
import com.itsaky.androidide.models.LogLine;
-import com.itsaky.androidide.models.PrefBasedJavaServerSettings;
+import com.itsaky.lsp.java.models.JavaServerSettings;
import com.itsaky.androidide.models.SaveResult;
import com.itsaky.androidide.models.SearchResult;
import com.itsaky.androidide.models.SheetOption;
@@ -1446,7 +1446,7 @@ public class EditorActivity extends StudioActivity
final var params = new InitializeParams(workspaceRoots);
javaLanguageServer.connectClient(client);
- javaLanguageServer.applySettings(PrefBasedJavaServerSettings.getInstance());
+ javaLanguageServer.applySettings(JavaServerSettings.getInstance());
javaLanguageServer.initialize(params);
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/preferences/BasePreferenceFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/preferences/BasePreferenceFragment.java
index 2bcddc884..3a0b1da3f 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/preferences/BasePreferenceFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/preferences/BasePreferenceFragment.java
@@ -1,8 +1,6 @@
-/************************************************************************************
+/*
* This file is part of AndroidIDE.
*
- *
- *
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,30 +14,33 @@
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see .
*
- **************************************************************************************/
-
+ */
package com.itsaky.androidide.fragments.preferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceFragmentCompat;
+
import com.itsaky.androidide.app.StudioApp;
import com.itsaky.androidide.managers.PreferenceManager;
public abstract class BasePreferenceFragment extends PreferenceFragmentCompat {
- protected PreferenceManager mPrefManager;
-
@Override
public View onCreateView(
- LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = super.onCreateView(inflater, container, savedInstanceState);
- v.setBackgroundColor(
- ContextCompat.getColor(
- StudioApp.getInstance(), com.itsaky.androidide.R.color.content_background));
+ if (v != null) {
+ v.setBackgroundColor(
+ ContextCompat.getColor(
+ StudioApp.getInstance(),
+ com.itsaky.androidide.R.color.content_background));
+ }
return v;
}
@@ -49,8 +50,6 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat {
}
protected PreferenceManager getPrefManager() {
- return mPrefManager == null
- ? mPrefManager = new PreferenceManager(getContext())
- : mPrefManager;
+ return StudioApp.getInstance().getPrefManager();
}
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/preferences/EditorPreferences.java b/app/src/main/java/com/itsaky/androidide/fragments/preferences/EditorPreferences.java
index bc2516dc6..bf2253e1a 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/preferences/EditorPreferences.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/preferences/EditorPreferences.java
@@ -31,8 +31,8 @@ import static com.itsaky.androidide.managers.PreferenceManager.KEY_EDITOR_HORIZO
import static com.itsaky.androidide.managers.PreferenceManager.KEY_EDITOR_PRINTABLE_CHARS;
import static com.itsaky.androidide.managers.PreferenceManager.KEY_EDITOR_TAB_SIZE;
import static com.itsaky.androidide.managers.PreferenceManager.KEY_EDITOR_USE_POPUP;
-import static com.itsaky.androidide.models.PrefBasedJavaServerSettings.KEY_JAVA_PREF_GOOGLE_CODE_STYLE;
-import static com.itsaky.androidide.models.PrefBasedJavaServerSettings.KEY_JAVA_PREF_MATCH_LOWER;
+import static com.itsaky.lsp.java.models.JavaServerSettings.KEY_JAVA_PREF_GOOGLE_CODE_STYLE;
+import static com.itsaky.lsp.java.models.JavaServerSettings.KEY_COMPLETIONS_MATCH_LOWER;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -47,7 +47,7 @@ import com.itsaky.androidide.R;
import com.itsaky.androidide.app.StudioApp;
import com.itsaky.androidide.databinding.LayoutTextSizeSliderBinding;
import com.itsaky.androidide.models.ConstantsBridge;
-import com.itsaky.androidide.models.PrefBasedJavaServerSettings;
+import com.itsaky.lsp.java.models.JavaServerSettings;
import com.itsaky.androidide.utils.DialogUtils;
public class EditorPreferences extends BasePreferenceFragment
@@ -121,7 +121,7 @@ public class EditorPreferences extends BasePreferenceFragment
autoSave.setTitle(getString(R.string.idepref_editor_autoSave_title));
autoSave.setSummary(getString(R.string.idepref_editor_autoSave_summary));
- javaMatchLower.setKey(KEY_JAVA_PREF_MATCH_LOWER);
+ javaMatchLower.setKey(KEY_COMPLETIONS_MATCH_LOWER);
javaMatchLower.setIcon(R.drawable.ic_text_lower);
javaMatchLower.setTitle(getString(R.string.idepref_java_matchLower_title));
javaMatchLower.setSummary(getString(R.string.idepref_java_matchLower_summary));
@@ -170,7 +170,7 @@ public class EditorPreferences extends BasePreferenceFragment
horizontalPopup.setChecked(getPrefManager().getBoolean(KEY_EDITOR_HORIZONTAL_POPUP, false));
drawHex.setChecked(getPrefManager().getBoolean(KEY_EDITOR_DRAW_HEX, true));
autoSave.setChecked(getPrefManager().getBoolean(KEY_EDITOR_AUTO_SAVE, false));
- javaMatchLower.setChecked(getPrefManager().getBoolean(KEY_JAVA_PREF_MATCH_LOWER, false));
+ javaMatchLower.setChecked(getPrefManager().getBoolean(KEY_COMPLETIONS_MATCH_LOWER, false));
useGoogleCodeStyle.setChecked(
getPrefManager().getBoolean(KEY_JAVA_PREF_GOOGLE_CODE_STYLE, false));
visiblePasswordFlag.setChecked(getPrefManager().getBoolean(KEY_EDITOR_FLAG_PASSWORD, true));
@@ -190,10 +190,6 @@ public class EditorPreferences extends BasePreferenceFragment
case KEY_EDITOR_FONT_LIGATURES:
ConstantsBridge.EDITOR_PREF_LIGATURES_CHANGED = true;
break;
- case KEY_JAVA_PREF_MATCH_LOWER:
- final var javaServer = StudioApp.getInstance().getJavaLanguageServer();
- javaServer.applySettings(PrefBasedJavaServerSettings.getInstance());
- break;
}
getPrefManager().putBoolean(preference.getKey(), value);
diff --git a/images/header.png b/images/header.png
new file mode 100644
index 000000000..2e8eafab5
Binary files /dev/null and b/images/header.png differ
diff --git a/lsp/api/src/main/java/com/itsaky/lsp/api/IServerSettings.java b/lsp/api/src/main/java/com/itsaky/lsp/api/IServerSettings.java
index 5d5c5d759..a6ec3a3d8 100644
--- a/lsp/api/src/main/java/com/itsaky/lsp/api/IServerSettings.java
+++ b/lsp/api/src/main/java/com/itsaky/lsp/api/IServerSettings.java
@@ -25,6 +25,8 @@ package com.itsaky.lsp.api;
*/
public interface IServerSettings {
+ String KEY_COMPLETIONS_MATCH_LOWER = "idepref_editor_completions_matchLower";
+
/**
* Called by language server to check if the completions are enabled. If not enabled, the server
* should not was time and memory computing completions.
diff --git a/lsp/api/src/main/java/com/itsaky/lsp/util/PrefBasedServerSettings.java b/lsp/api/src/main/java/com/itsaky/lsp/util/PrefBasedServerSettings.java
new file mode 100644
index 000000000..977580f3c
--- /dev/null
+++ b/lsp/api/src/main/java/com/itsaky/lsp/util/PrefBasedServerSettings.java
@@ -0,0 +1,56 @@
+/*
+ * This file is part of AndroidIDE.
+ *
+ * AndroidIDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AndroidIDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AndroidIDE. If not, see .
+ */
+
+package com.itsaky.lsp.util;
+
+import androidx.annotation.Nullable;
+
+import com.itsaky.androidide.app.BaseApplication;
+import com.itsaky.androidide.managers.PreferenceManager;
+import com.itsaky.lsp.api.IServerSettings;
+
+/**
+ * {@link IServerSettings} implementation which uses {@link
+ * com.itsaky.androidide.managers.PreferenceManager PreferencesManager} to read common settings.
+ *
+ * @author Akash Yadav
+ */
+public abstract class PrefBasedServerSettings extends DefaultServerSettings {
+
+ private PreferenceManager prefs;
+
+ @Nullable
+ public PreferenceManager getPrefs() {
+ if (prefs == null) {
+ final var app = BaseApplication.getBaseInstance();
+ if (app != null) {
+ prefs = app.getPrefManager();
+ }
+ }
+ return prefs;
+ }
+
+ @Override
+ public boolean shouldMatchAllLowerCase() {
+ final var prefs = getPrefs();
+ if (prefs != null) {
+ return prefs.getBoolean(KEY_COMPLETIONS_MATCH_LOWER, true);
+ }
+
+ return false;
+ }
+}
diff --git a/lsp/java/src/main/java/com/itsaky/lsp/java/JavaLanguageServer.java b/lsp/java/src/main/java/com/itsaky/lsp/java/JavaLanguageServer.java
index 61d246a67..6bd532519 100644
--- a/lsp/java/src/main/java/com/itsaky/lsp/java/JavaLanguageServer.java
+++ b/lsp/java/src/main/java/com/itsaky/lsp/java/JavaLanguageServer.java
@@ -19,6 +19,7 @@ package com.itsaky.lsp.java;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+
import com.itsaky.androidide.utils.Logger;
import com.itsaky.lsp.api.ICompletionProvider;
import com.itsaky.lsp.api.IDocumentHandler;
@@ -26,8 +27,8 @@ import com.itsaky.lsp.api.ILanguageClient;
import com.itsaky.lsp.api.ILanguageServer;
import com.itsaky.lsp.api.IServerSettings;
import com.itsaky.lsp.java.compiler.JavaCompilerService;
-import com.itsaky.lsp.java.models.DefaultJavaServerSettings;
import com.itsaky.lsp.java.models.JavaServerConfiguration;
+import com.itsaky.lsp.java.models.JavaServerSettings;
import com.itsaky.lsp.java.providers.CodeActionProvider;
import com.itsaky.lsp.java.providers.CodeFormatProvider;
import com.itsaky.lsp.java.providers.CompletionProvider;
@@ -54,6 +55,7 @@ import com.itsaky.lsp.models.ServerCapabilities;
import com.itsaky.lsp.models.SignatureHelp;
import com.itsaky.lsp.models.SignatureHelpParams;
import com.itsaky.lsp.util.NoCompletionsProvider;
+
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
@@ -89,7 +91,7 @@ public class JavaLanguageServer implements ILanguageServer, IDocumentHandler {
public IServerSettings getSettings() {
if (settings == null) {
- settings = new DefaultJavaServerSettings();
+ settings = JavaServerSettings.getInstance();
}
return settings;
diff --git a/lsp/java/src/main/java/com/itsaky/lsp/java/models/DefaultJavaServerSettings.java b/lsp/java/src/main/java/com/itsaky/lsp/java/models/DefaultJavaServerSettings.java
deleted file mode 100644
index 9ae6644e0..000000000
--- a/lsp/java/src/main/java/com/itsaky/lsp/java/models/DefaultJavaServerSettings.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This file is part of AndroidIDE.
- *
- * AndroidIDE is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * AndroidIDE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with AndroidIDE. If not, see .
- */
-
-package com.itsaky.lsp.java.models;
-
-import com.itsaky.lsp.util.DefaultServerSettings;
-
-/**
- * Default settings for the java language server.
- *
- * @author Akash Yadav
- */
-public class DefaultJavaServerSettings extends DefaultServerSettings {
- public static final int CODE_STYLE_AOSP = 0;
- public static final int CODE_STYLE_GOOGLE = 1;
-
- public int getCodeStyle() {
- return CODE_STYLE_AOSP;
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/models/PrefBasedJavaServerSettings.java b/lsp/java/src/main/java/com/itsaky/lsp/java/models/JavaServerSettings.java
similarity index 56%
rename from app/src/main/java/com/itsaky/androidide/models/PrefBasedJavaServerSettings.java
rename to lsp/java/src/main/java/com/itsaky/lsp/java/models/JavaServerSettings.java
index 8616c6c48..3f4cb8013 100644
--- a/app/src/main/java/com/itsaky/androidide/models/PrefBasedJavaServerSettings.java
+++ b/lsp/java/src/main/java/com/itsaky/lsp/java/models/JavaServerSettings.java
@@ -14,51 +14,41 @@
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see .
*/
-
-package com.itsaky.androidide.models;
+package com.itsaky.lsp.java.models;
import androidx.annotation.NonNull;
-import com.itsaky.androidide.app.StudioApp;
+
import com.itsaky.androidide.managers.PreferenceManager;
-import com.itsaky.lsp.java.models.DefaultJavaServerSettings;
+import com.itsaky.lsp.util.PrefBasedServerSettings;
/**
* Server settings for the java language server.
*
* @author Akash Yadav
*/
-public class PrefBasedJavaServerSettings extends DefaultJavaServerSettings {
+public class JavaServerSettings extends PrefBasedServerSettings {
- public static final String KEY_JAVA_PREF_MATCH_LOWER = "idepref_editor_java_matchLower";
public static final String KEY_JAVA_PREF_GOOGLE_CODE_STYLE =
"idepref_editor_java_googleCodeStyle";
-
- private static PrefBasedJavaServerSettings instance;
-
- private final PreferenceManager prefs;
-
- public PrefBasedJavaServerSettings() {
- this.prefs = StudioApp.getInstance().getPrefManager();
- }
+ public static final int CODE_STYLE_AOSP = 0;
+ public static final int CODE_STYLE_GOOGLE = 1;
+ private static JavaServerSettings instance;
@NonNull
- public static PrefBasedJavaServerSettings getInstance() {
+ public static JavaServerSettings getInstance() {
if (instance == null) {
- instance = new PrefBasedJavaServerSettings();
+ instance = new JavaServerSettings();
}
return instance;
}
- @Override
- public boolean shouldMatchAllLowerCase() {
- return prefs.getBoolean(KEY_JAVA_PREF_MATCH_LOWER, false);
- }
-
- @Override
public int getCodeStyle() {
- if (prefs.getBoolean(KEY_JAVA_PREF_GOOGLE_CODE_STYLE, false)) {
- return CODE_STYLE_GOOGLE;
+ final PreferenceManager prefs = getPrefs();
+ if (prefs != null) {
+ if (prefs.getBoolean(KEY_JAVA_PREF_GOOGLE_CODE_STYLE, false)) {
+ return CODE_STYLE_GOOGLE;
+ }
}
return CODE_STYLE_AOSP;
diff --git a/lsp/java/src/main/java/com/itsaky/lsp/java/providers/CodeFormatProvider.java b/lsp/java/src/main/java/com/itsaky/lsp/java/providers/CodeFormatProvider.java
index 63769b3cb..400e7ab07 100644
--- a/lsp/java/src/main/java/com/itsaky/lsp/java/providers/CodeFormatProvider.java
+++ b/lsp/java/src/main/java/com/itsaky/lsp/java/providers/CodeFormatProvider.java
@@ -20,13 +20,15 @@ package com.itsaky.lsp.java.providers;
import static com.itsaky.androidide.utils.Logger.instance;
import androidx.annotation.NonNull;
+
import com.google.common.io.CharSink;
import com.google.common.io.CharSource;
import com.google.googlejavaformat.java.Formatter;
import com.google.googlejavaformat.java.JavaFormatterOptions;
import com.itsaky.androidide.utils.Logger;
import com.itsaky.lsp.api.IServerSettings;
-import com.itsaky.lsp.java.models.DefaultJavaServerSettings;
+import com.itsaky.lsp.java.models.JavaServerSettings;
+
import java.io.StringWriter;
import java.io.Writer;
@@ -39,11 +41,11 @@ public class CodeFormatProvider {
private static final Logger LOG = instance("JavaCodeFormatProvider");
- private final DefaultJavaServerSettings settings;
+ private final JavaServerSettings settings;
public CodeFormatProvider(IServerSettings settings) {
- assert settings instanceof DefaultJavaServerSettings;
- this.settings = (DefaultJavaServerSettings) settings;
+ assert settings instanceof JavaServerSettings;
+ this.settings = (JavaServerSettings) settings;
}
public CharSequence format(CharSequence input) {
@@ -64,7 +66,7 @@ public class CodeFormatProvider {
return JavaFormatterOptions.builder()
.formatJavadoc(true)
.style(
- settings.getCodeStyle() == DefaultJavaServerSettings.CODE_STYLE_AOSP
+ settings.getCodeStyle() == JavaServerSettings.CODE_STYLE_AOSP
? JavaFormatterOptions.Style.AOSP
: JavaFormatterOptions.Style.GOOGLE)
.build();
diff --git a/lsp/xml/src/main/java/com/itsaky/lsp/xml/providers/CompletionProvider.java b/lsp/xml/src/main/java/com/itsaky/lsp/xml/providers/CompletionProvider.java
index c1dc64a23..0fca3fd58 100644
--- a/lsp/xml/src/main/java/com/itsaky/lsp/xml/providers/CompletionProvider.java
+++ b/lsp/xml/src/main/java/com/itsaky/lsp/xml/providers/CompletionProvider.java
@@ -19,6 +19,7 @@ package com.itsaky.lsp.xml.providers;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+
import com.itsaky.androidide.app.BaseApplication;
import com.itsaky.androidide.lexers.xml.XMLLexer;
import com.itsaky.androidide.utils.CharSequenceReader;
@@ -33,18 +34,21 @@ import com.itsaky.lsp.models.CompletionItemKind;
import com.itsaky.lsp.models.CompletionParams;
import com.itsaky.lsp.models.CompletionResult;
import com.itsaky.lsp.models.InsertTextFormat;
+import com.itsaky.lsp.util.StringUtils;
import com.itsaky.lsp.xml.R;
import com.itsaky.sdk.SDKInfo;
import com.itsaky.widgets.models.Widget;
+
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.Token;
+import org.jetbrains.annotations.Contract;
+
import java.nio.file.Path;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
-import org.antlr.v4.runtime.CharStreams;
-import org.antlr.v4.runtime.Token;
-import org.jetbrains.annotations.Contract;
/**
* Completion provider for the XML Language
@@ -70,6 +74,21 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
this.sdkInfo = sdkInfo;
}
+ @NonNull
+ @Contract(pure = true)
+ private static CompletionItem createNamespaceCompletion(String name, String value) {
+ final var item = new CompletionItem();
+ item.setLabel(name + "Ns");
+ item.setDetail(
+ BaseApplication.getBaseInstance().getString(R.string.msg_add_namespace_decl, name));
+ item.setInsertText(String.format("xmlns:%1$s=\"%2$s\"", name, value));
+ item.setKind(CompletionItemKind.SNIPPET);
+ item.setSortText(
+ "1000" + item.getLabel()); // This item is expected to be at the last of the
+ // completion list
+ return item;
+ }
+
@Override
public boolean canComplete(Path file) {
return ICompletionProvider.super.canComplete(file)
@@ -127,6 +146,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
return EMPTY;
}
+ final var matchLower = getSettings().shouldMatchAllLowerCase();
final var result = new CompletionResult();
final var attrs = sdkInfo.getAttrInfo();
// final var parser = XmlUtils.newParser (contents);
@@ -153,7 +173,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
if (attr != null && attr.hasPossibleValues()) {
Set values = attr.possibleValues;
for (String value : values) {
- if (value.toLowerCase(Locale.US).startsWith(prefix)) {
+ if (StringUtils.matchesPartialName(value, prefix, matchLower)) {
result.getItems().add(valueAsCompletion(value));
}
}
@@ -162,7 +182,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
} else {
for (Map.Entry entry : attrs.getAttributes().entrySet()) {
Attr attr = entry.getValue();
- if (attr.name.toLowerCase(Locale.US).startsWith(prefix)) {
+ if (StringUtils.matchesPartialName(attr.name, prefix, matchLower)) {
result.getItems().add(attrAsCompletion(attr));
}
}
@@ -170,15 +190,15 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
// Shortcuts for automatically declaring namespaces
// These completions are proposed if you type 'androidNs', 'appNs' or 'toolsNs'
// Idea is shamelessly copied from Android Studio 😂
- if ("android".startsWith(prefix)) {
+ if (StringUtils.matchesPartialName("android", prefix, matchLower)) {
result.getItems().add(createNamespaceCompletion("android", ANDROID_NS));
}
- if ("app".startsWith(prefix)) {
+ if (StringUtils.matchesPartialName("app", prefix, matchLower)) {
result.getItems().add(createNamespaceCompletion("app", APP_NS));
}
- if ("tools".startsWith(prefix)) {
+ if (StringUtils.matchesPartialName("tools", prefix, matchLower)) {
result.getItems().add(createNamespaceCompletion("tools", TOOLS_NS));
}
}
@@ -191,7 +211,8 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
prefix = prefix.toLowerCase(Locale.ROOT);
for (var widget : this.sdkInfo.getWidgetInfo().getWidgets()) {
var name = widget.simpleName.toLowerCase(Locale.ROOT);
- if (name.startsWith(prefix)) {
+ if (StringUtils.matchesPartialName(
+ name, prefix, getSettings().shouldMatchAllLowerCase())) {
result.getItems().add(widgetNameAsCompletion(widget, slash));
}
}
@@ -279,21 +300,6 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
return sb.toString();
}
- @NonNull
- @Contract(pure = true)
- private static CompletionItem createNamespaceCompletion(String name, String value) {
- final var item = new CompletionItem();
- item.setLabel(name + "Ns");
- item.setDetail(
- BaseApplication.getBaseInstance().getString(R.string.msg_add_namespace_decl, name));
- item.setInsertText(String.format("xmlns:%1$s=\"%2$s\"", name, value));
- item.setKind(CompletionItemKind.SNIPPET);
- item.setSortText(
- "1000" + item.getLabel()); // This item is expected to be at the last of the
- // completion list
- return item;
- }
-
private static class IsInValueScanner {
private final int cursorIndex;