Added M68kAddressRegisterWordAccessInspection

This commit is contained in:
2025-05-13 21:14:07 +02:00
parent 84eb1eab69
commit a3f979b48b
5 changed files with 129 additions and 9 deletions
@@ -0,0 +1,69 @@
package de.platon42.intellij.plugins.m68k.inspections
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemHighlightType
import de.platon42.intellij.plugins.m68k.asm.AddressMode
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.findMatchingInstructions
import de.platon42.intellij.plugins.m68k.asm.OP_SIZE_W
import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil
import de.platon42.intellij.plugins.m68k.psi.M68kAsmInstruction
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.findExactIsaDataAndAllowedAdrModeForInstruction
class M68kAddressRegisterWordAccessInspection : AbstractBaseM68kLocalInspectionTool() {
companion object {
private const val DISPLAY_NAME = "Word access to address register"
private const val ADDR_REG_WORD_ACCESS_MSG_TEMPLATE = "Suspicious %s %s address register"
}
override fun getDisplayName() = DISPLAY_NAME
override fun checkAsmInstruction(asmInstruction: M68kAsmInstruction, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? {
val asmOp = asmInstruction.asmOp
if (asmOp.opSize != OP_SIZE_W) return emptyArray()
val isaDataCandidates = findMatchingInstructions(asmOp.mnemonic)
if (isaDataCandidates.isEmpty()) return emptyArray()
val (isaData, adrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(asmInstruction) ?: return emptyArray()
return when (isaData.mnemonic) {
"movea" -> arrayOf(
manager.createProblemDescriptor(
asmInstruction,
asmInstruction,
ADDR_REG_WORD_ACCESS_MSG_TEMPLATE.format(isaData.mnemonic, "word write to"),
ProblemHighlightType.WARNING,
isOnTheFly
)
)
"cmpa" -> arrayOf(
manager.createProblemDescriptor(
asmInstruction,
asmInstruction,
ADDR_REG_WORD_ACCESS_MSG_TEMPLATE.format(isaData.mnemonic, "comparing with word-sized"),
ProblemHighlightType.WARNING,
isOnTheFly
)
)
"tst" -> if (M68kAddressModeUtil.getAddressModeForType(asmInstruction.addressingModeList.getOrNull(0)) == AddressMode.ADDRESS_REGISTER_DIRECT) {
arrayOf(
manager.createProblemDescriptor(
asmInstruction,
asmInstruction,
ADDR_REG_WORD_ACCESS_MSG_TEMPLATE.format(isaData.mnemonic, "with word-sized"),
ProblemHighlightType.WARNING,
isOnTheFly
)
)
} else {
emptyArray()
}
else -> emptyArray()
}
}
}
@@ -12,22 +12,26 @@ import de.platon42.intellij.plugins.m68k.psi.utils.M68kLookupUtil
class M68kGlobalLabelSymbolCompletionContributor : CompletionContributor() {
companion object {
val REGS = listOf(
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
"pc"
)
val REGSET = REGS.toSet()
val REGISTER_SUGGESTIONS: List<LookupElement> =
listOf(
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
"pc"
)
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.REGISTER).withBoldness(true), 2.0) }
REGS.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.REGISTER).withBoldness(true), 2.0) }
}
init {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.SYMBOL), object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
resultSet.addAllElements(REGISTER_SUGGESTIONS)
resultSet.addAllElements(M68kLookupUtil.findAllGlobalLabels(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
resultSet.addAllElements(M68kLookupUtil.findAllSymbolDefinitions(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
val prefix = resultSet.prefixMatcher.prefix.lowercase()
if (!(prefix == "a" || prefix == "d" || REGSET.contains(prefix))) {
resultSet.addAllElements(M68kLookupUtil.findAllGlobalLabels(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
resultSet.addAllElements(M68kLookupUtil.findAllSymbolDefinitions(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
}
}
})
}
}
}
+3
View File
@@ -77,6 +77,9 @@
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kUnresolvedReferenceInspection"
displayName="Unresolved label/symbol/macro reference" groupName="M68k"
enabledByDefault="true" level="WARNING"/>
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kAddressRegisterWordAccessInspection"
displayName="Suspicious word access to address register" groupName="M68k"
enabledByDefault="true" level="WARNING"/>
<projectService serviceImplementation="de.platon42.intellij.plugins.m68k.settings.M68kProjectSettings"/>
@@ -0,0 +1,29 @@
package de.platon42.intellij.plugins.m68k.inspections
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.MyFixture
import org.junit.jupiter.api.Test
internal class M68kAddressRegisterWordAccessInspectionTest : AbstractInspectionTest() {
@Test
internal fun shows_warning_on_movea_word_sized(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kAddressRegisterWordAccessInspection::class.java)
myFixture.configureByText("wordaccess.asm", " move.w d0,a0")
assertHighlightings(myFixture, 1, "Suspicious movea word write to address register")
}
@Test
internal fun shows_warning_on_cmpa_word_sized(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kAddressRegisterWordAccessInspection::class.java)
myFixture.configureByText("wordaccess.asm", " cmp.w d0,a0")
assertHighlightings(myFixture, 1, "Suspicious cmpa comparing with word-sized address register")
}
@Test
internal fun shows_warning_on_tst_with_word_sized_address_register(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kAddressRegisterWordAccessInspection::class.java)
myFixture.configureByText("wordaccess.asm", " tst.w a0")
assertHighlightings(myFixture, 1, "Suspicious tst with word-sized address register")
}
}