Skip to content

Commit

Permalink
#51 Migrate java inspections to kotlin
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Timofte committed Dec 1, 2024
1 parent c3256f0 commit bd18cb2
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 110 deletions.

This file was deleted.

30 changes: 30 additions & 0 deletions src/main/kotlin/ac/quant/quickfixspec/common/spec/XmlUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,34 @@ object XmlUtils {

return DEFINITION_GROUP_NAME.containsValue(parentTagName)
}

@JvmStatic
fun getCurrentTag(element: PsiElement): XmlTag {
if (element is XmlTag) {
return element
}

// iterate up the tree until we find the tag
var current = element
while (current !is XmlTag) {
current = current.parent
}
return current
}

//Check if the tag is a reference to a component tag
@JvmStatic
fun isComponentReference(tag: XmlTag): Boolean {
val parentTag = tag.parentTag ?: return false
if (parentTag.name == "components") {
return false
}

// if the tag is not self-closing that means it is a definition
if (tag.subTags.size > 0) {
return false
}

return true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package ac.quant.quickfixspec.inspections

import ac.quant.quickfixspec.common.spec.XmlUtils.findDefinition
import ac.quant.quickfixspec.common.spec.XmlUtils.getRootTag
import ac.quant.quickfixspec.common.spec.XmlUtils.isComponentReference
import ac.quant.quickfixspec.common.spec.XmlUtils.getCurrentTag

import ac.quant.quickfixspec.inspections.ReplaceWithDefinitionInspection.ReplaceWithDefinitionQuickFix
import com.intellij.codeInsight.intention.FileModifier.SafeFieldForPreview
import com.intellij.codeInspection.LocalInspectionTool
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.SmartPointerManager
import com.intellij.psi.SmartPsiElementPointer
import com.intellij.psi.xml.XmlTag
import com.intellij.util.IncorrectOperationException


class ReplaceWithDefinitionInspection : LocalInspectionTool() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : PsiElementVisitor() {
override fun visitElement(element: PsiElement) {
val rootTag = getRootTag(element) ?: return

val currentTag: XmlTag = getCurrentTag(element)
if (currentTag.name != "component") {
return
}


// return if the tag is not a component reference, and it's actually a definition from the "components" group
if (!isComponentReference(currentTag)) {
return
}

val componentName = currentTag.getAttributeValue("name") ?: return
val definition = findDefinition(componentName, "component", rootTag) ?: return

// check if we didn't already register a problem for this tag
if (holder.isOnTheFly && holder.results.any { it.psiElement == currentTag }) {
return
}

holder.registerProblem(currentTag, "Replace with definition", ReplaceWithDefinitionQuickFix(definition))
}
}
}

private class ReplaceWithDefinitionQuickFix(definition: XmlTag) : LocalQuickFix {
@SafeFieldForPreview
private val definitionPointer: SmartPsiElementPointer<XmlTag?> = SmartPointerManager.createPointer<XmlTag?>(definition)

override fun getName(): String {
return "Replace component reference with definition"
}

override fun getFamilyName(): String {
return name
}

@Throws(IncorrectOperationException::class)
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
// Get the <component> tag that is to be replaced
val tagToReplace = descriptor.psiElement as XmlTag

// Retrieve the full definition of the <component> from the pointer
val definition = definitionPointer.getElement()

if (definition != null) {
// Create a copy of the definition tag to be inserted
val newTag = definition.copy() as XmlTag

// Replace the original <component> tag with the full definition
tagToReplace.replace(newTag)
}
}
}
}
25 changes: 22 additions & 3 deletions src/test/kotlin/ac/quant/quickfixspec/common/spec/TestXmlUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class TestXmlUtils : BasePlatformTestCase() {
}
}


fun testFindDefinition() {
val psiFile = getXmlFile(myFixture, "FIX44.xml")
val rootTag = psiFile.findElementAt(0)!!.parent as XmlTag
Expand Down Expand Up @@ -111,10 +110,8 @@ class TestXmlUtils : BasePlatformTestCase() {
}
}


fun testIsTagDeclaration() {
val psiFile = getXmlFile(myFixture, "FIX44.xml")
val rootTag = psiFile.findElementAt(0)!!.parent as XmlTag

val indexes = arrayOf(2650, 2785, 108734, 167517)
val expectedDeclarations = arrayOf(false, false, true, true)
Expand All @@ -133,6 +130,28 @@ class TestXmlUtils : BasePlatformTestCase() {

}

fun testGetCurrentTag() {
val psiFile = getXmlFile(myFixture, "FIX44.xml")

val expectedTagsMap = mapOf(
0 to "fix",
2650 to "field",
2785 to "component",
4879 to "message",
12818 to "group",
108734 to "component",
167517 to "field"
)

for (positionInFile in expectedTagsMap.keys) {
val expectedTag = expectedTagsMap[positionInFile]!!
val psiElement = psiFile.findElementAt(positionInFile)!!

val currentTag = XmlUtils.getCurrentTag(psiElement)
assertEquals("Current tag for element at positionInFile $positionInFile should be '$expectedTag' but was '${currentTag.name}'", expectedTag, currentTag.name)
}
}

override fun getTestDataPath() = "src/main/resources/spec"

}

0 comments on commit bd18cb2

Please sign in to comment.