mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
Added attribute completion provider for XML drawables and animations
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
# **AndroidIDE v2.1.1-beta**
|
||||||
|
|
||||||
|
This is a patch release which fixes a bug.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Bug which caused AbstractMethodError in Tooling API implementation.
|
||||||
+27
-5
@@ -18,6 +18,8 @@
|
|||||||
package com.itsaky.androidide.lsp.xml.providers
|
package com.itsaky.androidide.lsp.xml.providers
|
||||||
|
|
||||||
import com.android.SdkConstants.ANDROID_MANIFEST_XML
|
import com.android.SdkConstants.ANDROID_MANIFEST_XML
|
||||||
|
import com.android.aaptcompiler.AaptResourceType.ANIM
|
||||||
|
import com.android.aaptcompiler.AaptResourceType.DRAWABLE
|
||||||
import com.android.aaptcompiler.AaptResourceType.LAYOUT
|
import com.android.aaptcompiler.AaptResourceType.LAYOUT
|
||||||
import com.android.aaptcompiler.ResourcePathData
|
import com.android.aaptcompiler.ResourcePathData
|
||||||
import com.android.aaptcompiler.extractPathData
|
import com.android.aaptcompiler.extractPathData
|
||||||
@@ -27,14 +29,19 @@ import com.itsaky.androidide.lsp.api.IServerSettings
|
|||||||
import com.itsaky.androidide.lsp.models.CompletionParams
|
import com.itsaky.androidide.lsp.models.CompletionParams
|
||||||
import com.itsaky.androidide.lsp.models.CompletionResult
|
import com.itsaky.androidide.lsp.models.CompletionResult
|
||||||
import com.itsaky.androidide.lsp.models.CompletionResult.Companion.EMPTY
|
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.AttrValueCompletionProvider
|
import com.itsaky.androidide.lsp.xml.providers.completion.AttrValueCompletionProvider
|
||||||
|
import com.itsaky.androidide.lsp.xml.providers.completion.IXmlCompletionProvider
|
||||||
|
import com.itsaky.androidide.lsp.xml.providers.completion.canCompleteManifest
|
||||||
|
import com.itsaky.androidide.lsp.xml.providers.completion.common.CommonAttrCompletionProvider
|
||||||
import com.itsaky.androidide.lsp.xml.providers.completion.layout.LayoutAttrCompletionProvider
|
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.layout.LayoutTagCompletionProvider
|
||||||
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.ManifestAttrCompletionProvider
|
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.ManifestAttrCompletionProvider
|
||||||
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.ManifestAttrValueCompletionProvider
|
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.ManifestAttrValueCompletionProvider
|
||||||
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.ManifestTagCompletionProvider
|
import com.itsaky.androidide.lsp.xml.providers.completion.manifest.ManifestTagCompletionProvider
|
||||||
import com.itsaky.androidide.lsp.xml.providers.completion.canCompleteManifest
|
import com.itsaky.androidide.lsp.xml.utils.AnimTagTransformer
|
||||||
|
import com.itsaky.androidide.lsp.xml.utils.DrawableTagTransformer
|
||||||
|
import com.itsaky.androidide.lsp.xml.utils.ITagTransformer
|
||||||
|
import com.itsaky.androidide.lsp.xml.utils.NoOpTagTransformer
|
||||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils
|
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
|
||||||
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.ATTRIBUTE
|
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.ATTRIBUTE
|
||||||
@@ -46,10 +53,10 @@ import com.itsaky.androidide.utils.ILogger
|
|||||||
import com.itsaky.androidide.utils.StopWatch
|
import com.itsaky.androidide.utils.StopWatch
|
||||||
import com.itsaky.xml.INamespace
|
import com.itsaky.xml.INamespace
|
||||||
import io.github.rosemoe.sora.text.ContentReference
|
import io.github.rosemoe.sora.text.ContentReference
|
||||||
import java.io.IOException
|
|
||||||
import java.io.Reader
|
|
||||||
import org.eclipse.lemminx.dom.DOMParser
|
import org.eclipse.lemminx.dom.DOMParser
|
||||||
import org.eclipse.lemminx.uriresolver.URIResolverExtensionManager
|
import org.eclipse.lemminx.uriresolver.URIResolverExtensionManager
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.Reader
|
||||||
import kotlin.io.path.name
|
import kotlin.io.path.name
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,10 +138,25 @@ class XmlCompletionProvider(settings: IServerSettings) :
|
|||||||
return when (pathData.type) {
|
return when (pathData.type) {
|
||||||
LAYOUT -> createLayoutCompleter(type)
|
LAYOUT -> createLayoutCompleter(type)
|
||||||
null -> createNullTypeCompleter(pathData, type)
|
null -> createNullTypeCompleter(pathData, type)
|
||||||
|
else -> createCommonCompleter(pathData, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCommonCompleter(pathData: ResourcePathData, type: NodeType): IXmlCompletionProvider? {
|
||||||
|
return when(type) {
|
||||||
|
ATTRIBUTE -> CommonAttrCompletionProvider( tagTransformerFor(pathData),this)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun tagTransformerFor(pathData: ResourcePathData): ITagTransformer {
|
||||||
|
return when(pathData.type) {
|
||||||
|
ANIM -> AnimTagTransformer
|
||||||
|
DRAWABLE -> DrawableTagTransformer
|
||||||
|
else -> NoOpTagTransformer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createNullTypeCompleter(
|
private fun createNullTypeCompleter(
|
||||||
pathData: ResourcePathData,
|
pathData: ResourcePathData,
|
||||||
type: NodeType
|
type: NodeType
|
||||||
|
|||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.common
|
||||||
|
|
||||||
|
import com.android.aaptcompiler.ConfigDescription
|
||||||
|
import com.android.aaptcompiler.ResourceGroup
|
||||||
|
import com.android.aaptcompiler.Styleable
|
||||||
|
import com.itsaky.androidide.lsp.api.ICompletionProvider
|
||||||
|
import com.itsaky.androidide.lsp.xml.providers.completion.AttrCompletionProvider
|
||||||
|
import com.itsaky.androidide.lsp.xml.utils.ITagTransformer
|
||||||
|
import org.eclipse.lemminx.dom.DOMNode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides attribute completion for all other resource types.
|
||||||
|
*
|
||||||
|
* @property tagTransform A function which returns the styleable entry name for the given tag name
|
||||||
|
* (first param) and its parent's tag name (second param).
|
||||||
|
* @author Akash Yadav
|
||||||
|
*/
|
||||||
|
internal class CommonAttrCompletionProvider(
|
||||||
|
private val tagTransform: ITagTransformer,
|
||||||
|
provider: ICompletionProvider
|
||||||
|
) : AttrCompletionProvider(provider) {
|
||||||
|
|
||||||
|
override fun findNodeStyleables(node: DOMNode, styleables: ResourceGroup): Set<Styleable> {
|
||||||
|
val name = node.nodeName
|
||||||
|
val styleable =
|
||||||
|
styleables
|
||||||
|
.findEntry(tagTransform.transform(name, nodeAtCursor.parentNode?.nodeName ?: ""))
|
||||||
|
?.findValue(ConfigDescription())
|
||||||
|
?.value
|
||||||
|
if (styleable != null && styleable is Styleable) {
|
||||||
|
return setOf(styleable)
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptySet()
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -23,6 +23,7 @@ import com.android.aaptcompiler.ResourcePathData
|
|||||||
import com.android.aaptcompiler.Styleable
|
import com.android.aaptcompiler.Styleable
|
||||||
import com.itsaky.androidide.lsp.api.ICompletionProvider
|
import com.itsaky.androidide.lsp.api.ICompletionProvider
|
||||||
import com.itsaky.androidide.lsp.xml.providers.completion.AttrCompletionProvider
|
import com.itsaky.androidide.lsp.xml.providers.completion.AttrCompletionProvider
|
||||||
|
import com.itsaky.androidide.lsp.xml.providers.completion.MANIFEST_TAG_PREFIX
|
||||||
import com.itsaky.androidide.lsp.xml.providers.completion.canCompleteManifest
|
import com.itsaky.androidide.lsp.xml.providers.completion.canCompleteManifest
|
||||||
import com.itsaky.androidide.lsp.xml.providers.completion.manifestResourceTable
|
import com.itsaky.androidide.lsp.xml.providers.completion.manifestResourceTable
|
||||||
import com.itsaky.androidide.lsp.xml.providers.completion.transformToEntryName
|
import com.itsaky.androidide.lsp.xml.providers.completion.transformToEntryName
|
||||||
@@ -46,7 +47,7 @@ class ManifestAttrCompletionProvider(provider: ICompletionProvider) :
|
|||||||
override fun findNodeStyleables(node: DOMNode, styleables: ResourceGroup): Set<Styleable> {
|
override fun findNodeStyleables(node: DOMNode, styleables: ResourceGroup): Set<Styleable> {
|
||||||
val name = node.nodeName
|
val name = node.nodeName
|
||||||
val styleable =
|
val styleable =
|
||||||
styleables.findEntry(transformToEntryName(name))?.findValue(ConfigDescription())?.value
|
styleables.findEntry(transformToEntryName(name, MANIFEST_TAG_PREFIX))?.findValue(ConfigDescription())?.value
|
||||||
if (styleable != null && styleable is Styleable) {
|
if (styleable != null && styleable is Styleable) {
|
||||||
return setOf(styleable)
|
return setOf(styleable)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -74,7 +74,7 @@ class ManifestTagCompletionProvider(provider: ICompletionProvider) :
|
|||||||
|
|
||||||
styleables
|
styleables
|
||||||
.findEntries { it.startsWith(MANIFEST_TAG_PREFIX) }
|
.findEntries { it.startsWith(MANIFEST_TAG_PREFIX) }
|
||||||
.map { transformToTagName(it.name) }
|
.map { transformToTagName(it.name, MANIFEST_TAG_PREFIX) }
|
||||||
.forEach {
|
.forEach {
|
||||||
val match = matchLevel(it, newPrefix)
|
val match = matchLevel(it, newPrefix)
|
||||||
if (match == NO_MATCH) {
|
if (match == NO_MATCH) {
|
||||||
|
|||||||
+1
-56
@@ -38,59 +38,4 @@ fun manifestResourceTable(): Set<ResourceTable> {
|
|||||||
return setOf(
|
return setOf(
|
||||||
Lookup.DEFAULT.lookup(ResourceTableRegistry.COMPLETION_MANIFEST_ATTR_RES) ?: return emptySet()
|
Lookup.DEFAULT.lookup(ResourceTableRegistry.COMPLETION_MANIFEST_ATTR_RES) ?: return emptySet()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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()
|
|
||||||
}
|
|
||||||
+56
-1
@@ -55,4 +55,59 @@ fun findAllNamespaces(node: DOMNode): MutableSet<Pair<String, String>> {
|
|||||||
curr = curr.parentNode
|
curr = curr.parentNode
|
||||||
}
|
}
|
||||||
return namespaces
|
return namespaces
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms entry name to tag name.
|
||||||
|
*
|
||||||
|
* For example: `AndroidManifestUsesPermission` -> `uses-permission`
|
||||||
|
*/
|
||||||
|
fun transformToTagName(entryName: String, prefix: String = ""): String {
|
||||||
|
val name = StringBuilder()
|
||||||
|
var index = prefix.length
|
||||||
|
while (index < entryName.length) {
|
||||||
|
var c = entryName[index]
|
||||||
|
if (c.isUpperCase()) {
|
||||||
|
if (index != 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, prefix: String = ""): String {
|
||||||
|
if (tagName == "manifest") {
|
||||||
|
return MANIFEST_TAG_PREFIX
|
||||||
|
}
|
||||||
|
|
||||||
|
val name = StringBuilder(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()
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
import com.itsaky.androidide.lsp.xml.providers.completion.transformToEntryName
|
||||||
|
|
||||||
|
/** Transforms tag names to styleable entry names. */
|
||||||
|
internal interface ITagTransformer {
|
||||||
|
/** Returns the styleable entry name for the given tag name and its parent's tag name. */
|
||||||
|
fun transform(tag: String, parent: String = ""): String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object NoOpTagTransformer : ITagTransformer {
|
||||||
|
override fun transform(tag: String, parent: String): String {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object DrawableTagTransformer : ITagTransformer {
|
||||||
|
override fun transform(tag: String, parent: String): String {
|
||||||
|
if (tag == "corners") {
|
||||||
|
return "DrawableCorners"
|
||||||
|
}
|
||||||
|
|
||||||
|
val prefix =
|
||||||
|
if (parent.isNotEmpty()) {
|
||||||
|
toEntry(parent).run { if (startsWith('#')) toEntry(tag) else this }
|
||||||
|
} else tag
|
||||||
|
val suffix =
|
||||||
|
if (parent.isNotEmpty() && !parent.startsWith('#')) transformToEntryName(tag) else ""
|
||||||
|
|
||||||
|
return "${prefix}Drawable${suffix}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object AnimTagTransformer : ITagTransformer {
|
||||||
|
override fun transform(tag: String, parent: String): String {
|
||||||
|
if (tag == "set") {
|
||||||
|
return "AnimationSet"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "${toEntry(tag)}${animEntrySuffix(tag)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the suffix that is required to get the styleable entry for an anim resource. */
|
||||||
|
private fun animEntrySuffix(tag: String): String {
|
||||||
|
return when {
|
||||||
|
tag.endsWith("Animation") -> ""
|
||||||
|
tag.endsWith("Interpolator") -> ""
|
||||||
|
else -> "Animation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the tag name to entry name.
|
||||||
|
*
|
||||||
|
* @param tag The tag name.
|
||||||
|
*/
|
||||||
|
private fun toEntry(tag: String): String {
|
||||||
|
if (tag.startsWith('#')) {
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
when (tag) {
|
||||||
|
"selector" -> return "StateList"
|
||||||
|
"animated-selector" -> return "AnimatedStateList"
|
||||||
|
"animation" -> return "Animation"
|
||||||
|
"shape" -> return "Gradient"
|
||||||
|
}
|
||||||
|
|
||||||
|
return transformToEntryName(tag)
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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 CommonAttrCompletionProviderTest : CompletionHelper by CompletionHelperImpl() {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() = XMLLSPTest.initProjectIfNeeded()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test simple drawable attributes`() {
|
||||||
|
XMLLSPTest.apply {
|
||||||
|
openFile("../res/drawable/TestDrawableAttrs")
|
||||||
|
val (incomplete, items) = complete()
|
||||||
|
assertThat(incomplete).isFalse()
|
||||||
|
assertThat(items).contains("android:shape")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
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 TagTransformsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test drawable tag transforms`() {
|
||||||
|
val tagMap =
|
||||||
|
mapOf(
|
||||||
|
"selector" to "StateListDrawable",
|
||||||
|
"animated-selector" to "AnimatedStateListDrawable",
|
||||||
|
"animation" to "AnimationDrawable",
|
||||||
|
"shape" to "GradientDrawable",
|
||||||
|
"corners" to "DrawableCorners",
|
||||||
|
"layer" to "LayerDrawable",
|
||||||
|
"level-list" to "LevelListDrawable",
|
||||||
|
"rotate" to "RotateDrawable",
|
||||||
|
"animated-rotate" to "AnimatedRotateDrawable",
|
||||||
|
"inset" to "InsetDrawable",
|
||||||
|
"bitmap" to "BitmapDrawable",
|
||||||
|
"nine-patch" to "NinePatchDrawable",
|
||||||
|
"adaptive-icon" to "AdaptiveIconDrawable",
|
||||||
|
"ripple" to "RippleDrawable",
|
||||||
|
"scale" to "ScaleDrawable",
|
||||||
|
"clip" to "ClipDrawable",
|
||||||
|
"vector" to "VectorDrawable",
|
||||||
|
"animated-vector" to "AnimatedVectorDrawable"
|
||||||
|
)
|
||||||
|
|
||||||
|
tagMap.forEach { (tag, entry) ->
|
||||||
|
assertThat(DrawableTagTransformer.transform(tag, "#document")).isEqualTo(entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test drawable sub tag transforms`() {
|
||||||
|
val tags =
|
||||||
|
listOf(
|
||||||
|
Triple("item", "selector", "StateListDrawableItem"),
|
||||||
|
Triple("item", "animated-selector", "AnimatedStateListDrawableItem"),
|
||||||
|
Triple("transition", "animated-selector", "AnimatedStateListDrawableTransition"),
|
||||||
|
Triple("size", "shape", "GradientDrawableSize"),
|
||||||
|
Triple("padding", "shape", "GradientDrawablePadding"),
|
||||||
|
Triple("gradient", "shape", "GradientDrawableGradient")
|
||||||
|
)
|
||||||
|
|
||||||
|
tags.forEach {
|
||||||
|
assertThat(DrawableTagTransformer.transform(it.first, it.second)).isEqualTo(it.third)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test animation tag transforms`() {
|
||||||
|
val tagMap =
|
||||||
|
mapOf(
|
||||||
|
"set" to "AnimationSet",
|
||||||
|
"rotate" to "RotateAnimation",
|
||||||
|
"scale" to "ScaleAnimation",
|
||||||
|
"gridLayoutAnimation" to "GridLayoutAnimation",
|
||||||
|
"accelerateInterpolator" to "AccelerateInterpolator",
|
||||||
|
"accelerateDecelerateInterpolator" to "AccelerateDecelerateInterpolator"
|
||||||
|
)
|
||||||
|
|
||||||
|
tagMap.forEach { (tag, entry) ->
|
||||||
|
assertThat(AnimTagTransformer.transform(tag)).isEqualTo(entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
sh@@cursor@@>
|
||||||
|
</shape>
|
||||||
Reference in New Issue
Block a user