Compare commits

..

No commits in common. "main" and "feat/formatter" have entirely different histories.

7 changed files with 20 additions and 141 deletions

View File

@ -1,4 +1,4 @@
# MC68000 Assembly Language Plugin
# MC68000 Assembly Language Plugin [![Build Status](https://app.travis-ci.com/chrisly42/mc68000-asm-plugin.svg?branch=main)](https://app.travis-ci.com/chrisly42/mc68000-asm-plugin) [![Coverage Status](https://coveralls.io/repos/github/chrisly42/mc68000-asm-plugin/badge.svg?branch=main)](https://coveralls.io/github/chrisly42/mc68000-asm-plugin?branch=main)
_MC68000 Assembly Language Plugin_ is plugin for Jetbrains IDEs (CLion, IntelliJ, etc.).
@ -84,17 +84,6 @@ optimize the order of execution.
Points out unresolved references such for global and local labels, macros or symbols. Right now, missing symbol and global label references are shown only as
weak warnings as missing macro evaluation will not resolve symbols defined via `STRUCT` macros.
#### M68kAddressRegisterWordAccessInspection - Suspicious word access to address register
Warns on `movea.w` to address registers which is often a typo and takes ages to find and fix.
Of course there are legal intentional uses of this instruction that sign extends the word
to a long word, or using it as a temporary register or for index purposes.
Also warns on `cmpa.w` with address register as second operand (there are some clever ways
using this, such as using `cmpa.w ax,ax` to see if a value is between $ffff8000 and $7fff).
Third instruction checked is `tst.w` on address registers for 68020+.
### Documentation provider
#### M68kSymbolDefinition
@ -161,10 +150,9 @@ to highlight the same address and data registers while editing (see new `View ->
## Development notice
This plugin has been written in Kotlin 1.9 using Grammar-Kit.
This plugin has been written in Kotlin 1.7 using Grammar-Kit.
It is probably the only plugin (besides [Cajon](https://git.platon42.de/chrisly42/cajon-plugin) from the same author) that uses JUnit 5 Jupiter for unit testing
so
It is probably the only plugin (besides [Cajon](https://github.com/chrisly42/cajon-plugin) from the same author) that uses JUnit 5 Jupiter for unit testing so
far (or at least the only one I'm aware of ;) ). The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing, and it took me quite a while to
make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for your projects (with attribution).
@ -177,10 +165,6 @@ are appreciated. It really is keeping me motivated to continue development.
## Changelog
### V0.11 (unreleased)
- New: Added M68kAddressRegisterWordAccessInspection to find suspicious uses of address registers.
### V0.10 (20-Feb-24)
- Decided to release some features that have been sitting on my harddrive for almost two years, but never got released,

View File

@ -6,7 +6,7 @@ plugins {
}
group = 'de.platon42'
version = '0.10'
version = '0.11'
sourceCompatibility = 17
targetCompatibility = 17
@ -21,12 +21,12 @@ repositories {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
testImplementation 'org.assertj:assertj-core:3.26.3'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.2'
testImplementation 'org.assertj:assertj-core:3.25.3'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.2'
testImplementation "org.jetbrains.kotlin:kotlin-test"
testImplementation "org.jetbrains.kotlin:kotlin-reflect"
testImplementation 'org.junit.platform:junit-platform-launcher:1.11.2'
testImplementation 'org.junit.platform:junit-platform-launcher:1.10.2'
// testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
}

View File

@ -1,4 +1,4 @@
kotlin.code.style=official
kotlin.incremental=true
intellijPublishToken=perm:dummy
systemProp.jdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2"
systemProp.jdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2"

View File

@ -1,69 +0,0 @@
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()
}
}
}

View File

@ -12,26 +12,22 @@ 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> =
REGS.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.REGISTER).withBoldness(true), 2.0) }
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) }
}
init {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.SYMBOL), object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
resultSet.addAllElements(REGISTER_SUGGESTIONS)
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))
}
resultSet.addAllElements(M68kLookupUtil.findAllGlobalLabels(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
resultSet.addAllElements(M68kLookupUtil.findAllSymbolDefinitions(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
}
})
}
}
}

View File

@ -1,14 +1,14 @@
<idea-plugin>
<id>de.platon42.m68k</id>
<name>MC68000 Assembly Language Support</name>
<vendor email="chrisly@platon42.de" url="https://git.platon42.de/chrisly42/mc68000-asm-plugin">Chris 'platon42' Hodges
<vendor email="chrisly@platon42.de" url="https://github.com/chrisly42/mc68000-asm-plugin">Chris 'platon42' Hodges
</vendor>
<description><![CDATA[
MC68000 Assembly Language Plugin adds language support for Motorola 68000 (M68k) assembly language files (asm).
It provides syntax highlighting and refactoring possibilities among other things.
<p>
<a href="https://git.platon42.de/chrisly42/mc68000-asm-plugin/blob/main/README.md">Full documentation here...</a>
<a href="https://github.com/chrisly42/mc68000-asm-plugin/blob/main/README.md">Full documentation here...</a>
]]></description>
<idea-version since-build="203.5981.166"/>
@ -77,9 +77,6 @@
<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"/>

View File

@ -1,29 +0,0 @@
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")
}
}