mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 15:56:48 +08:00
Added completion provider for manifest attributes
This commit is contained in:
+6
-4
@@ -29,10 +29,11 @@ import com.itsaky.androidide.lsp.models.CompletionResult
|
||||
import com.itsaky.androidide.lsp.models.CompletionResult.Companion.EMPTY
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.IXmlCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.common.AttrValueCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.layout.LayoutAttributeCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.layout.LayoutAttrCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.layout.LayoutTagCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.ManifestCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.ManifestAttrCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.ManifestTagCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.canCompleteManifest
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.ATTRIBUTE
|
||||
@@ -134,7 +135,7 @@ class XmlCompletionProvider(settings: IServerSettings) :
|
||||
): IXmlCompletionProvider? {
|
||||
|
||||
// In test cases
|
||||
if (ManifestCompletionProvider.canComplete(pathData, type)) {
|
||||
if (canCompleteManifest(pathData, type)) {
|
||||
return createManifestCompleter(type)
|
||||
}
|
||||
|
||||
@@ -147,6 +148,7 @@ class XmlCompletionProvider(settings: IServerSettings) :
|
||||
private fun createManifestCompleter(type: NodeType): IXmlCompletionProvider? {
|
||||
return when (type) {
|
||||
TAG -> ManifestTagCompletionProvider(this)
|
||||
ATTRIBUTE -> ManifestAttrCompletionProvider(this)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -154,7 +156,7 @@ class XmlCompletionProvider(settings: IServerSettings) :
|
||||
private fun createLayoutCompleter(type: NodeType): IXmlCompletionProvider? {
|
||||
return when (type) {
|
||||
TAG -> LayoutTagCompletionProvider(this)
|
||||
ATTRIBUTE -> LayoutAttributeCompletionProvider(this)
|
||||
ATTRIBUTE -> LayoutAttrCompletionProvider(this)
|
||||
ATTRIBUTE_VALUE -> AttrValueCompletionProvider(this)
|
||||
else -> null
|
||||
}
|
||||
|
||||
+20
-16
@@ -15,7 +15,7 @@
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.lsp.xml.providers.completion.layout
|
||||
package com.itsaky.androidide.lsp.xml.providers.completion
|
||||
|
||||
import com.android.aaptcompiler.AaptResourceType.STYLEABLE
|
||||
import com.android.aaptcompiler.ConfigDescription
|
||||
@@ -29,8 +29,8 @@ import com.itsaky.androidide.lsp.models.CompletionItem
|
||||
import com.itsaky.androidide.lsp.models.CompletionParams
|
||||
import com.itsaky.androidide.lsp.models.CompletionResult
|
||||
import com.itsaky.androidide.lsp.models.MatchLevel.NO_MATCH
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.AttributeCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.ATTRIBUTE
|
||||
import com.itsaky.androidide.xml.widgets.Widget
|
||||
import com.itsaky.androidide.xml.widgets.WidgetTable
|
||||
import org.eclipse.lemminx.dom.DOMDocument
|
||||
@@ -41,9 +41,13 @@ import org.eclipse.lemminx.dom.DOMNode
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
AttributeCompletionProvider(provider) {
|
||||
|
||||
open class AttrCompletionProvider(provider: ICompletionProvider) :
|
||||
IXmlCompletionProvider(provider) {
|
||||
|
||||
override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean {
|
||||
return super.canProvideCompletions(pathData, type) && type == ATTRIBUTE
|
||||
}
|
||||
|
||||
override fun doComplete(
|
||||
params: CompletionParams,
|
||||
pathData: ResourcePathData,
|
||||
@@ -96,7 +100,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
return CompletionResult(list)
|
||||
}
|
||||
|
||||
private fun completeForNamespace(
|
||||
protected open fun completeForNamespace(
|
||||
namespace: String,
|
||||
nsPrefix: String,
|
||||
node: DOMNode,
|
||||
@@ -125,7 +129,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun addFromPackage(
|
||||
protected open fun addFromPackage(
|
||||
tablePackage: ResourceTablePackage?,
|
||||
node: DOMNode,
|
||||
pck: String,
|
||||
@@ -148,7 +152,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
)
|
||||
}
|
||||
|
||||
private fun addFromStyleables(
|
||||
protected open fun addFromStyleables(
|
||||
styleables: Set<Styleable>,
|
||||
pck: String,
|
||||
pckPrefix: String,
|
||||
@@ -173,7 +177,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun findNodeStyleables(node: DOMNode, styleables: ResourceGroup): Set<Styleable> {
|
||||
protected open fun findNodeStyleables(node: DOMNode, styleables: ResourceGroup): Set<Styleable> {
|
||||
val nodeName = node.nodeName
|
||||
val widgets = Lookup.DEFAULT.lookup(WidgetTable.COMPLETION_LOOKUP_KEY) ?: return emptySet()
|
||||
|
||||
@@ -199,7 +203,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
private fun findStyleablesForName(
|
||||
protected open fun findStyleablesForName(
|
||||
styleables: ResourceGroup,
|
||||
node: DOMNode,
|
||||
addFromParent: Boolean = false,
|
||||
@@ -231,7 +235,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findLayoutParams(styleables: ResourceGroup, parentNode: DOMNode): Set<Styleable> {
|
||||
protected open fun findLayoutParams(styleables: ResourceGroup, parentNode: DOMNode): Set<Styleable> {
|
||||
val result = mutableSetOf<Styleable>()
|
||||
|
||||
// Add layout params common for all view groups and the ones supporting child margins
|
||||
@@ -248,7 +252,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findStyleablesForWidget(
|
||||
protected open fun findStyleablesForWidget(
|
||||
styleables: ResourceGroup,
|
||||
widgets: WidgetTable,
|
||||
widget: Widget,
|
||||
@@ -293,7 +297,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
return result
|
||||
}
|
||||
|
||||
private fun addWidgetStyleable(
|
||||
protected open fun addWidgetStyleable(
|
||||
styleables: ResourceGroup,
|
||||
widget: Widget,
|
||||
result: MutableSet<Styleable>,
|
||||
@@ -302,7 +306,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
addWidgetStyleable(styleables, widget.simpleName, result, suffix)
|
||||
}
|
||||
|
||||
private fun addWidgetStyleable(
|
||||
protected open fun addWidgetStyleable(
|
||||
styleables: ResourceGroup,
|
||||
widget: String,
|
||||
result: MutableSet<Styleable>,
|
||||
@@ -314,7 +318,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun addSuperclassStyleables(
|
||||
protected open fun addSuperclassStyleables(
|
||||
styleables: ResourceGroup,
|
||||
widgets: WidgetTable,
|
||||
widget: Widget,
|
||||
@@ -332,7 +336,7 @@ class LayoutAttributeCompletionProvider(provider: ICompletionProvider) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun findStyleableEntry(styleables: ResourceGroup, name: String): Styleable? {
|
||||
protected open fun findStyleableEntry(styleables: ResourceGroup, name: String): Styleable? {
|
||||
val value = styleables.findEntry(name)?.findValue(ConfigDescription())?.value
|
||||
if (value !is Styleable) {
|
||||
return null
|
||||
+1
-1
@@ -45,7 +45,7 @@ import org.eclipse.lemminx.dom.DOMDocument
|
||||
*/
|
||||
abstract class IXmlCompletionProvider(private val provider: ICompletionProvider) {
|
||||
|
||||
protected val log = ILogger.newInstance("XmlCompletionProvider")
|
||||
protected val log: ILogger = ILogger.newInstance("XmlCompletionProvider")
|
||||
|
||||
companion object {
|
||||
const val NAMESPACE_PREFIX = "http://schemas.android.com/apk/res/"
|
||||
|
||||
+5
-5
@@ -17,20 +17,20 @@
|
||||
|
||||
package com.itsaky.androidide.lsp.xml.providers.completion.layout
|
||||
|
||||
import com.android.aaptcompiler.AaptResourceType.LAYOUT
|
||||
import com.android.aaptcompiler.ResourcePathData
|
||||
import com.itsaky.androidide.lsp.api.ICompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.IXmlCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.AttrCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType
|
||||
|
||||
/**
|
||||
* Base class for completion providers providing completions in a layout file.
|
||||
* Attribute completion provider for layout files.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
abstract class LayoutCompletionProvider(provider: ICompletionProvider) : IXmlCompletionProvider(provider) {
|
||||
class LayoutAttrCompletionProvider(provider: ICompletionProvider) :
|
||||
AttrCompletionProvider(provider) {
|
||||
|
||||
override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean {
|
||||
return super.canProvideCompletions(pathData, type) && pathData.type == LAYOUT
|
||||
return super.canProvideCompletions(pathData, type) && canCompleteLayout(pathData, type)
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -35,10 +35,10 @@ import org.eclipse.lemminx.dom.DOMDocument
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
open class LayoutTagCompletionProvider(val provider: ICompletionProvider) :
|
||||
LayoutCompletionProvider(provider) {
|
||||
IXmlCompletionProvider(provider) {
|
||||
|
||||
override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean {
|
||||
return super.canProvideCompletions(pathData, type) && type == TAG
|
||||
return super.canProvideCompletions(pathData, type) && canCompleteLayout(pathData, type) && type == TAG
|
||||
}
|
||||
|
||||
override fun doComplete(
|
||||
|
||||
+5
-11
@@ -15,22 +15,16 @@
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.lsp.xml.providers.completion
|
||||
package com.itsaky.androidide.lsp.xml.providers.completion.layout
|
||||
|
||||
import com.android.aaptcompiler.AaptResourceType.LAYOUT
|
||||
import com.android.aaptcompiler.ResourcePathData
|
||||
import com.itsaky.androidide.lsp.api.ICompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.ATTRIBUTE
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
* Base class for providing attribute completions in XML file.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
abstract class AttributeCompletionProvider(provider: ICompletionProvider) : IXmlCompletionProvider(provider) {
|
||||
|
||||
override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean {
|
||||
return super.canProvideCompletions(pathData, type) && type == ATTRIBUTE
|
||||
}
|
||||
}
|
||||
fun canCompleteLayout(pathData: ResourcePathData, type: NodeType) : Boolean {
|
||||
return pathData.type == LAYOUT
|
||||
}
|
||||
+29
-17
@@ -17,32 +17,44 @@
|
||||
|
||||
package com.itsaky.androidide.lsp.xml.providers.completion.manifest
|
||||
|
||||
import com.android.SdkConstants
|
||||
import com.android.aaptcompiler.ConfigDescription
|
||||
import com.android.aaptcompiler.ResourceGroup
|
||||
import com.android.aaptcompiler.ResourcePathData
|
||||
import com.android.aaptcompiler.ResourceTable
|
||||
import com.android.aaptcompiler.Styleable
|
||||
import com.itsaky.androidide.lookup.Lookup
|
||||
import com.itsaky.androidide.lsp.api.ICompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.IXmlCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.AttrCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType
|
||||
import com.itsaky.androidide.utils.VMUtils
|
||||
import com.itsaky.androidide.xml.resources.ResourceTableRegistry
|
||||
import org.eclipse.lemminx.dom.DOMNode
|
||||
|
||||
/**
|
||||
* Base class for completers which provide completions in Android manifest.
|
||||
* Provides attribution completion for AndroidManifest.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
abstract class ManifestCompletionProvider(provider: ICompletionProvider) :
|
||||
IXmlCompletionProvider(provider) {
|
||||
class ManifestAttrCompletionProvider(provider: ICompletionProvider) :
|
||||
AttrCompletionProvider(provider) {
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun canComplete(pathData: ResourcePathData, type: NodeType) : Boolean {
|
||||
return pathData.file.name == SdkConstants.ANDROID_MANIFEST_XML ||
|
||||
(VMUtils.isJvm() &&
|
||||
pathData.file.name.startsWith("Manifest") &&
|
||||
pathData.file.name.endsWith("_template.xml"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean {
|
||||
return super.canProvideCompletions(pathData, type) && canComplete(pathData, type)
|
||||
return super.canProvideCompletions(pathData, type) && canCompleteManifest(pathData, type)
|
||||
}
|
||||
|
||||
override fun findResourceTables(nsUri: String): Set<ResourceTable> {
|
||||
return setOf(
|
||||
Lookup.DEFAULT.lookup(ResourceTableRegistry.COMPLETION_MANIFEST_ATTR_RES) ?: return emptySet()
|
||||
)
|
||||
}
|
||||
|
||||
override fun findNodeStyleables(node: DOMNode, styleables: ResourceGroup): Set<Styleable> {
|
||||
val name = node.nodeName
|
||||
val styleable =
|
||||
styleables.findEntry(transformToEntryName(name))?.findValue(ConfigDescription())?.value
|
||||
if (styleable != null && styleable is Styleable) {
|
||||
return setOf(styleable)
|
||||
}
|
||||
|
||||
return emptySet()
|
||||
}
|
||||
}
|
||||
+6
-26
@@ -27,6 +27,7 @@ import com.itsaky.androidide.lsp.models.CompletionParams
|
||||
import com.itsaky.androidide.lsp.models.CompletionResult
|
||||
import com.itsaky.androidide.lsp.models.CompletionResult.Companion.EMPTY
|
||||
import com.itsaky.androidide.lsp.models.MatchLevel.NO_MATCH
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.IXmlCompletionProvider
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.TAG
|
||||
import com.itsaky.androidide.xml.resources.ResourceTableRegistry
|
||||
@@ -38,14 +39,12 @@ import org.eclipse.lemminx.dom.DOMDocument
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class ManifestTagCompletionProvider(provider: ICompletionProvider) :
|
||||
ManifestCompletionProvider(provider) {
|
||||
|
||||
companion object {
|
||||
private const val MANIFEST_TAG_PREFIX = "AndroidManifest"
|
||||
}
|
||||
IXmlCompletionProvider(provider) {
|
||||
|
||||
override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean {
|
||||
return super.canProvideCompletions(pathData, type) && type == TAG
|
||||
return super.canProvideCompletions(pathData, type) &&
|
||||
canCompleteManifest(pathData, type) &&
|
||||
type == TAG
|
||||
}
|
||||
|
||||
override fun doComplete(
|
||||
@@ -72,7 +71,7 @@ class ManifestTagCompletionProvider(provider: ICompletionProvider) :
|
||||
|
||||
styleables
|
||||
.findEntries { it.startsWith(MANIFEST_TAG_PREFIX) }
|
||||
.map { transformTagName(it.name) }
|
||||
.map { transformToTagName(it.name) }
|
||||
.forEach {
|
||||
val match = matchLevel(it, newPrefix)
|
||||
if (match == NO_MATCH) {
|
||||
@@ -84,23 +83,4 @@ class ManifestTagCompletionProvider(provider: ICompletionProvider) :
|
||||
|
||||
return CompletionResult(result)
|
||||
}
|
||||
|
||||
private fun transformTagName(tag: String): String {
|
||||
val name = StringBuilder()
|
||||
var index = MANIFEST_TAG_PREFIX.length
|
||||
while (index < tag.length) {
|
||||
var c = tag[index]
|
||||
if (c.isUpperCase()) {
|
||||
if (index != MANIFEST_TAG_PREFIX.length) {
|
||||
name.append('-')
|
||||
}
|
||||
c = c.lowercaseChar()
|
||||
}
|
||||
|
||||
name.append(c)
|
||||
++index
|
||||
}
|
||||
|
||||
return name.toString()
|
||||
}
|
||||
}
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.lsp.xml.providers.completion.manifest
|
||||
|
||||
import com.android.SdkConstants.ANDROID_MANIFEST_XML
|
||||
import com.android.aaptcompiler.ResourcePathData
|
||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType
|
||||
import com.itsaky.androidide.utils.VMUtils
|
||||
|
||||
const val MANIFEST_TAG_PREFIX = "AndroidManifest"
|
||||
|
||||
fun canCompleteManifest(pathData: ResourcePathData, type: NodeType): Boolean {
|
||||
return pathData.file.name == ANDROID_MANIFEST_XML ||
|
||||
(VMUtils.isJvm() &&
|
||||
pathData.file.name.startsWith("Manifest") &&
|
||||
pathData.file.name.endsWith("_template.xml"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms entry name to tag name.
|
||||
*
|
||||
* For example: `AndroidManifestUsesPermission` -> `uses-permission`
|
||||
*/
|
||||
fun transformToTagName(entryName: String): String {
|
||||
val name = StringBuilder()
|
||||
var index = MANIFEST_TAG_PREFIX.length
|
||||
while (index < entryName.length) {
|
||||
var c = entryName[index]
|
||||
if (c.isUpperCase()) {
|
||||
if (index != MANIFEST_TAG_PREFIX.length) {
|
||||
name.append('-')
|
||||
}
|
||||
c = c.lowercaseChar()
|
||||
}
|
||||
|
||||
name.append(c)
|
||||
++index
|
||||
}
|
||||
return name.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms entry name to tag name.
|
||||
*
|
||||
* For example: `uses-permission` -> `AndroidManifestUsesPermission`
|
||||
*/
|
||||
fun transformToEntryName(tagName: String): String {
|
||||
if (tagName == "manifest") {
|
||||
return MANIFEST_TAG_PREFIX
|
||||
}
|
||||
|
||||
val name = StringBuilder(MANIFEST_TAG_PREFIX)
|
||||
|
||||
var index = 0
|
||||
var capitalize = false
|
||||
while (index < tagName.length) {
|
||||
var c = tagName[index]
|
||||
if (c == '-') {
|
||||
capitalize = true
|
||||
++index
|
||||
continue
|
||||
}
|
||||
if (index == 0 || capitalize) {
|
||||
c = c.uppercaseChar()
|
||||
capitalize = false
|
||||
}
|
||||
name.append(c)
|
||||
++index
|
||||
}
|
||||
|
||||
return name.toString()
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.lsp.xml.providers.completion
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.itsaky.androidide.lsp.xml.CompletionHelper
|
||||
import com.itsaky.androidide.lsp.xml.CompletionHelperImpl
|
||||
import com.itsaky.androidide.lsp.xml.XMLLSPTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
/** @author Akash Yadav */
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(manifest = Config.NONE)
|
||||
class ManifestAttrCompletionProviderTest : CompletionHelper by CompletionHelperImpl() {
|
||||
|
||||
@Before fun setup() = XMLLSPTest.initProjectIfNeeded()
|
||||
|
||||
@Test // prefix: 'version'
|
||||
fun `test manifest tag attributes`() {
|
||||
XMLLSPTest.apply {
|
||||
openFile("completion/ManifestAttrTest")
|
||||
val (incomplete, items) = complete()
|
||||
assertThat(incomplete).isFalse()
|
||||
assertThat(items)
|
||||
.containsAtLeast("android:versionName", "android:versionCode", "android:versionCodeMajor")
|
||||
}
|
||||
}
|
||||
|
||||
@Test // prefix: 'allow'
|
||||
fun `test manifest application tag attributes`() {
|
||||
XMLLSPTest.apply {
|
||||
openFile("completion/ManifestApplicationAttrTest")
|
||||
val (incomplete, items) = complete()
|
||||
assertThat(incomplete).isFalse()
|
||||
assertThat(items)
|
||||
.containsAtLeast(
|
||||
"android:allowBackup",
|
||||
"android:allowClearUserDataOnFailedRestore",
|
||||
"android:allowAudioPlaybackCapture",
|
||||
"android:allowNativeHeapPointerTagging",
|
||||
"android:allowAutoRevokePermissionsExemption"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
+22
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.itsaky.test.app">
|
||||
|
||||
<application
|
||||
allow@@cursor@@
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.itsaky.test.app"
|
||||
version@@cursor@@>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
Reference in New Issue
Block a user