Macro definitions are now word and indexed, macro calls reference to definition.

Macro definition refactoring and find usages support.
Structural View also shows macro definitions.
Missing REPT and ENDR assembler directives added.
Changed or added some icons at various places.
Reference search for global labels and symbols now uses stub index.
This commit is contained in:
Chris Hodges 2021-07-27 16:34:49 +02:00
parent 6e683eb6a0
commit 25450a9bf8
54 changed files with 649 additions and 114 deletions

View File

@ -72,6 +72,12 @@ make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.
### V0.3 (unreleased)
- Enhancement: Macros contents are no longer parsed, added syntax highlighting options for macros.
- Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
- Enhancement: Macro definition refactoring and find usages support.
- Enhancement: Structural View also shows macro definitions.
- Bugfix: Missing REPT and ENDR assembler directives added.
- Cosmetics: Changed or added some icons at various places.
- Performance: Reference search for global labels and symbols now uses stub index.
### V0.2 (27-Jul-21)

View File

@ -49,6 +49,12 @@ patchPluginXml {
<h4>V0.3 (unreleased)</h4>
<ul>
<li>Enhancement: Macros contents are no longer parsed, added syntax highlighting options for macros.
<li>Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
<li>Enhancement: Macro definition refactoring and find usages support.
<li>Enhancement: Structural View also shows macro definitions.
<li>Bugfix: Missing REPT and ENDR assembler directives added.
<li>Cosmetics: Changed or added some icons at various places.
<li>Performance: Reference search for global labels and symbols now uses stub index.
</ul>
<h4>V0.2 (27-Jul-21)</h4>
<ul>

View File

@ -898,17 +898,13 @@ public class _M68kLexer implements FlexLexer {
yybegin(EXPR);
return OTHER_DIRECTIVE;
}
yybegin(MACROCALL);
eatOneWhitespace = true;
return MACRO_INVOKATION;
return handleMacroMode(this);
}
// fall through
case 116:
break;
case 8: {
yybegin(MACROCALL);
eatOneWhitespace = true;
return MACRO_INVOKATION;
return handleMacroMode(this);
}
// fall through
case 117:

View File

@ -551,7 +551,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
// AsmInstruction | MacroCall
static boolean Instruction(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "Instruction")) return false;
if (!nextTokenIs(b, "", MACRO_INVOKATION, MNEMONIC)) return false;
if (!nextTokenIs(b, "", MACRO_INVOCATION, MNEMONIC)) return false;
boolean r;
r = AsmInstruction(b, l + 1);
if (!r) r = MacroCall(b, l + 1);
@ -638,13 +638,13 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// MACRO_INVOKATION PlainOperands?
// MACRO_INVOCATION PlainOperands?
public static boolean MacroCall(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroCall")) return false;
if (!nextTokenIs(b, MACRO_INVOKATION)) return false;
if (!nextTokenIs(b, MACRO_INVOCATION)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, MACRO_INVOKATION);
r = consumeToken(b, MACRO_INVOCATION);
r = r && MacroCall_1(b, l + 1);
exit_section_(b, m, MACRO_CALL, r);
return r;
@ -754,19 +754,27 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// STRINGLIT (SEPARATOR STRINGLIT)*
// (expr|AddressingMode) (SEPARATOR (expr|AddressingMode))*
static boolean PlainOperands(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands")) return false;
if (!nextTokenIs(b, STRINGLIT)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, STRINGLIT);
r = PlainOperands_0(b, l + 1);
r = r && PlainOperands_1(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// (SEPARATOR STRINGLIT)*
// expr|AddressingMode
private static boolean PlainOperands_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_0")) return false;
boolean r;
r = expr(b, l + 1, -1);
if (!r) r = AddressingMode(b, l + 1);
return r;
}
// (SEPARATOR (expr|AddressingMode))*
private static boolean PlainOperands_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_1")) return false;
while (true) {
@ -777,16 +785,26 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true;
}
// SEPARATOR STRINGLIT
// SEPARATOR (expr|AddressingMode)
private static boolean PlainOperands_1_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_1_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeTokens(b, 0, SEPARATOR, STRINGLIT);
r = consumeToken(b, SEPARATOR);
r = r && PlainOperands_1_0_1(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// expr|AddressingMode
private static boolean PlainOperands_1_0_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_1_0_1")) return false;
boolean r;
r = expr(b, l + 1, -1);
if (!r) r = AddressingMode(b, l + 1);
return r;
}
/* ********************************************************** */
// Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
// PreprocessorOperands?

View File

@ -1,6 +1,19 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public interface M68kMacroCall extends M68kPsiElement {
@NotNull
List<M68kAddressingMode> getAddressingModeList();
@NotNull
List<M68kExpr> getExprList();
@NotNull
String getMacroName();
}

View File

@ -1,11 +1,15 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.StubBasedPsiElement;
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface M68kMacroDefinition extends M68kPsiElement {
public interface M68kMacroDefinition extends M68kNamedElement, StubBasedPsiElement<M68kMacroDefinitionStub> {
@NotNull
M68kMacroNameDefinition getMacroNameDefinition();
@ -13,4 +17,13 @@ public interface M68kMacroDefinition extends M68kPsiElement {
@NotNull
List<M68kMacroPlainLine> getMacroPlainLineList();
@Nullable
String getName();
@NotNull
PsiElement setName(@NotNull String name);
@NotNull
PsiElement getNameIdentifier();
}

View File

@ -51,7 +51,7 @@ public interface M68kTypes {
IElementType LITERAL_EXPR = new M68kElementType("LITERAL_EXPR");
IElementType LOCAL_LABEL = new M68kElementType("LOCAL_LABEL");
IElementType MACRO_CALL = new M68kElementType("MACRO_CALL");
IElementType MACRO_DEFINITION = new M68kElementType("MACRO_DEFINITION");
IElementType MACRO_DEFINITION = M68kStubElementTypeFactory.stubFactory("MACRO_DEFINITION");
IElementType MACRO_NAME_DEFINITION = new M68kElementType("MACRO_NAME_DEFINITION");
IElementType MACRO_PLAIN_LINE = new M68kElementType("MACRO_PLAIN_LINE");
IElementType OPERAND_SIZE = new M68kElementType("OPERAND_SIZE");
@ -90,7 +90,7 @@ public interface M68kTypes {
IElementType HEXADECIMAL = new M68kTokenType("HEXADECIMAL");
IElementType LOCAL_LABEL_DEF = new M68kTokenType("LOCAL_LABEL_DEF");
IElementType MACRO_END_TAG = new M68kTokenType("MACRO_END_TAG");
IElementType MACRO_INVOKATION = new M68kTokenType("MACRO_INVOKATION");
IElementType MACRO_INVOCATION = new M68kTokenType("MACRO_INVOCATION");
IElementType MACRO_LINE = new M68kTokenType("MACRO_LINE");
IElementType MACRO_NAME = new M68kTokenType("MACRO_NAME");
IElementType MACRO_TAG = new M68kTokenType("MACRO_TAG");

View File

@ -95,7 +95,7 @@ public class M68kVisitor extends PsiElementVisitor {
}
public void visitMacroDefinition(@NotNull M68kMacroDefinition o) {
visitPsiElement(o);
visitNamedElement(o);
}
public void visitMacroNameDefinition(@NotNull M68kMacroNameDefinition o) {

View File

@ -1,14 +1,15 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.*;
import org.jetbrains.annotations.NotNull;
public class M68kMacroCallImpl extends ASTWrapperPsiElement implements M68kMacroCall {
import java.util.List;
public class M68kMacroCallImpl extends M68kMacroCallMixin implements M68kMacroCall {
public M68kMacroCallImpl(@NotNull ASTNode node) {
super(node);
@ -24,4 +25,22 @@ public class M68kMacroCallImpl extends ASTWrapperPsiElement implements M68kMacro
else super.accept(visitor);
}
@Override
@NotNull
public List<M68kAddressingMode> getAddressingModeList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kAddressingMode.class);
}
@Override
@NotNull
public List<M68kExpr> getExprList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kExpr.class);
}
@Override
@NotNull
public String getMacroName() {
return M68kPsiImplUtil.getMacroName(this);
}
}

View File

@ -1,24 +1,28 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroNameDefinition;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroPlainLine;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import de.platon42.intellij.plugins.m68k.psi.*;
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class M68kMacroDefinitionImpl extends ASTWrapperPsiElement implements M68kMacroDefinition {
public class M68kMacroDefinitionImpl extends M68kMacroDefinitionMixin implements M68kMacroDefinition {
public M68kMacroDefinitionImpl(@NotNull ASTNode node) {
super(node);
}
public M68kMacroDefinitionImpl(@NotNull M68kMacroDefinitionStub stub, @NotNull IStubElementType<?, ?> nodeType) {
super(stub, nodeType);
}
public void accept(@NotNull M68kVisitor visitor) {
visitor.visitMacroDefinition(this);
}
@ -41,4 +45,22 @@ public class M68kMacroDefinitionImpl extends ASTWrapperPsiElement implements M68
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kMacroPlainLine.class);
}
@Override
@Nullable
public String getName() {
return M68kPsiImplUtil.getName(this);
}
@Override
@NotNull
public PsiElement setName(@NotNull String name) {
return M68kPsiImplUtil.setName(this, name);
}
@Override
@NotNull
public PsiElement getNameIdentifier() {
return M68kPsiImplUtil.getNameIdentifier(this);
}
}

View File

@ -10,7 +10,7 @@ class M68kFileElementType private constructor() : ILightStubFileElementType<PsiF
@JvmField
val INSTANCE = M68kFileElementType()
const val STUB_VERSION = 3
const val STUB_VERSION = 4
const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE"
}

View File

@ -7,5 +7,6 @@ object M68kIcons {
val FILE = IconLoader.getIcon("/icons/FileType_m68k.svg", javaClass)
val LOCAL_LABEL = AllIcons.Nodes.AbstractMethod
val GLOBAL_LABEL = AllIcons.Nodes.Method
val SYMBOL_DEF = AllIcons.Nodes.Constant
val SYMBOL_DEF = AllIcons.Nodes.ClassInitializer
val MACRO_DEF = AllIcons.Nodes.MultipleTypeDefinitions
}

View File

@ -3,46 +3,48 @@ package de.platon42.intellij.plugins.m68k.asm
object AssemblerDirectives {
val dataDirectives: Set<String> = setOf(
"section", "pushsection", "popsection",
"bss", "bss_c", "bss_f",
"data", "data_c", "data_f",
"text", "cseg", "code", "code_c", "code_f",
"offset",
"section", "pushsection", "popsection",
"bss", "bss_c", "bss_f",
"data", "data_c", "data_f",
"text", "cseg", "code", "code_c", "code_f",
"offset",
"abs",
"db", "dw", "dl",
"dr.b", "dr.w", "dr.l",
"dc", "dc.b", "dc.w", "dc.l", "dcb", "dcb.b", "dcb.w", "dcb.l",
"blk.b", "blk.w", "blk.l",
"ds", "ds.b", "ds.w", "ds.l",
"abs",
"db", "dw", "dl",
"dr.b", "dr.w", "dr.l",
"dc", "dc.b", "dc.w", "dc.l", "dcb", "dcb.b", "dcb.w", "dcb.l",
"blk.b", "blk.w", "blk.l",
"ds", "ds.b", "ds.w", "ds.l",
"align", "even", "odd", "cnop", "long", "dphrase", "phrase", "qphrase",
"align", "even", "odd", "cnop", "long", "dphrase", "phrase", "qphrase",
"cargs", "comm", "comment",
"rsset", "clrfo", "clrso", "setfo", "setso"
"cargs", "comm", "comment",
"rsset", "clrfo", "clrso", "setfo", "setso"
)
val otherDirective: Set<String> = setOf(
"if",
"ifeq", "ifne", "ifgt", "ifge", "iflt", "ifle", "ifb", "ifnb", "ifc", "ifnc",
"ifd", "ifnd", "ifmacrod", "ifmacrond",
//"iif" // not supported
"else", "endif", "endc",
"if",
"ifeq", "ifne", "ifgt", "ifge", "iflt", "ifle", "ifb", "ifnb", "ifc", "ifnc",
"ifd", "ifnd", "ifmacrod", "ifmacrond",
//"iif" // not supported
"else", "endif", "endc",
"macro", "exitm", "mexit", "endm",
"rept", "endr",
"extern", "nref", "xdef", "xref", "globl", "public", "weak",
"macro", "exitm", "mexit", "endm",
"reg", "equr", "equrl",
"extern", "nref", "xdef", "xref", "globl", "public", "weak",
"incdir", "include", "incbin", "output",
"reg", "equr", "equrl",
"list", "nlist", "nolist", "llen", "nopage", "page", "spc",
"org",
"incdir", "include", "incbin", "output",
"assert", "fail", "print", "printt", "printv", "echo",
"list", "nlist", "nolist", "llen", "nopage", "page", "spc",
"org",
"inline", "einline",
"rem", "erem"
"assert", "fail", "print", "printt", "printv", "echo",
"inline", "einline",
"rem", "erem"
)
}

View File

@ -2,15 +2,22 @@ package de.platon42.intellij.plugins.m68k.asm
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.icons.AllIcons
import com.intellij.patterns.PlatformPatterns
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
class M68kMnemonicCompletionContributor : CompletionContributor() {
companion object {
val MNEMONICS = M68kIsa.mnemonics
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(AllIcons.Nodes.Protected), 10.0) }
}
init {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.MACRO_INVOKATION), object : CompletionProvider<CompletionParameters>() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.MACRO_INVOCATION), object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
resultSet.addAllElements(M68kIsa.mnemonics.map(LookupElementBuilder::create))
resultSet.addAllElements(MNEMONICS)
}
})
}

View File

@ -4,6 +4,7 @@ import com.intellij.psi.TokenType
import com.intellij.psi.tree.IElementType
import de.platon42.intellij.plugins.m68k.asm.AssemblerDirectives
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.mnemonics
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
object LexerUtil {
@ -48,6 +49,17 @@ object LexerUtil {
return TokenType.WHITE_SPACE
}
@JvmStatic
fun handleMacroMode(lexer: _M68kLexer): IElementType {
if (lexer.lexerPrefs.macroParametersUnparsed) {
lexer.yybegin(_M68kLexer.MACROCALL)
} else {
lexer.yybegin(_M68kLexer.ASMOPS)
}
lexer.eatOneWhitespace = true
return M68kTypes.MACRO_INVOCATION
}
@JvmStatic
fun handleMacroLineEol(lexer: _M68kLexer): IElementType {
if (++lexer.macroLines > lexer.lexerPrefs.maxLinesPerMacro) {

View File

@ -89,10 +89,10 @@ PLAIN_MACRO_LINE=[^;\r\n]+
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
if(isDataDirective(yytext())) { yybegin(EXPR); return DATA_DIRECTIVE; }
if(isOtherDirective(yytext())) { yybegin(EXPR); return OTHER_DIRECTIVE; }
yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION;
return handleMacroMode(this);
}
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { yybegin(INSTRPART); return SYMBOL; } }
{MACRONAME} { yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION; }
{MACRONAME} { return handleMacroMode(this); }
{HASH_COMMENT} { yybegin(YYINITIAL); return COMMENT; }
}
@ -107,10 +107,10 @@ PLAIN_MACRO_LINE=[^;\r\n]+
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
if(isDataDirective(yytext())) { yybegin(EXPR); return DATA_DIRECTIVE; }
if(isOtherDirective(yytext())) { yybegin(EXPR); return OTHER_DIRECTIVE; }
yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION;
return handleMacroMode(this);
}
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { return SYMBOL; } }
{MACRONAME} { yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION; }
{MACRONAME} { return handleMacroMode(this); }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
@ -130,10 +130,10 @@ PLAIN_MACRO_LINE=[^;\r\n]+
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
"," { return SEPARATOR; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
{PLAINPARAM} { return STRINGLIT; }
}

View File

@ -173,9 +173,22 @@ PreprocessorDirective ::= Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
MacroPlainLine ::= MACRO_LINE
MacroNameDefinition ::= MACRO_NAME
MacroDefinition ::= ((MacroNameDefinition MACRO_TAG)|(MACRO_TAG MacroNameDefinition)) MacroPlainLine* MACRO_END_TAG {pin=1}
MacroDefinition ::= ((MacroNameDefinition MACRO_TAG)|(MACRO_TAG MacroNameDefinition)) MacroPlainLine* MACRO_END_TAG {
pin=1
name = "macro definition"
implements = "de.platon42.intellij.plugins.m68k.psi.M68kNamedElement"
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinitionMixin"
elementTypeFactory = "de.platon42.intellij.plugins.m68k.stubs.M68kStubElementTypeFactory.stubFactory"
stubClass = "de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub"
methods = [getName setName getNameIdentifier]
}
MacroCall ::= MACRO_INVOCATION PlainOperands? {
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kMacroCallMixin"
methods = [getMacroName]
}
MacroCall ::= MACRO_INVOKATION PlainOperands?
AsmInstruction ::= AsmOp AsmOperands?
private Instruction ::= AsmInstruction | MacroCall
//external Instruction ::= parseMacroCallOrAsmInstruction
@ -185,7 +198,7 @@ private AsmOperands ::= AddressingMode (SEPARATOR AddressingMode)?
private PreprocessorOperands ::= PreprocessorOperand (SEPARATOR PreprocessorOperand)*
private PreprocessorOperand ::= expr
private PlainOperands ::= STRINGLIT (SEPARATOR STRINGLIT)*
private PlainOperands ::= (expr|AddressingMode) (SEPARATOR (expr|AddressingMode))*
// TODO This should probably be a ILazyParseableElementType, no idea how to implement that yet
SymbolReference ::= SYMBOL {

View File

@ -27,6 +27,16 @@ object M68kElementFactory {
return PsiTreeUtil.findChildOfType(file, M68kSymbolReference::class.java)!!
}
fun createMacroDefinition(project: Project, name: String): M68kMacroDefinition {
val file = createFile(project, "$name macro\nendm\n")
return PsiTreeUtil.findChildOfType(file, M68kMacroDefinition::class.java)!!
}
fun createMacroCall(project: Project, name: String): M68kMacroCall {
val file = createFile(project, " $name\n")
return PsiTreeUtil.findChildOfType(file, M68kMacroCall::class.java)!!
}
fun createFile(project: Project, content: String): M68kFile {
return PsiFileFactory.getInstance(project).createFileFromText("dummy.m68k", INSTANCE, content) as M68kFile
}

View File

@ -5,6 +5,7 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
object M68kLookupUtil {
@ -93,4 +94,47 @@ object M68kLookupUtil {
}
fun findAllSymbolDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kSymbolDefinitionStubIndex.KEY, project)
fun findAllMacroDefinitions(project: Project): List<M68kMacroDefinition> {
val results: MutableList<M68kMacroDefinition> = ArrayList()
StubIndex.getInstance().processAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
{
results.addAll(
StubIndex.getElements(
M68kMacroDefinitionStubIndex.KEY,
it,
project,
GlobalSearchScope.allScope(project),
M68kMacroDefinition::class.java
)
)
true
}
return results
}
fun findAllMacroDefinitions(file: M68kFile): List<M68kMacroDefinition> {
val results: MutableList<M68kMacroDefinition> = ArrayList()
StubIndex.getInstance().processAllKeys(
M68kMacroDefinitionStubIndex.KEY,
{
results.addAll(
StubIndex.getElements(
M68kMacroDefinitionStubIndex.KEY,
it,
file.project,
GlobalSearchScope.fileScope(file),
M68kMacroDefinition::class.java
)
)
true
}, GlobalSearchScope.fileScope(file), null
)
return results
}
fun findAllMacroDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
}

View File

@ -0,0 +1,13 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiReference
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
abstract class M68kMacroCallMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kMacroCall {
override fun getReferences(): Array<PsiReference> {
return ReferenceProvidersRegistry.getReferencesFromProviders(this)
}
}

View File

@ -0,0 +1,29 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.StubBasedPsiElementBase
import com.intellij.ide.projectView.PresentationData
import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import com.intellij.psi.stubs.IStubElementType
import de.platon42.intellij.plugins.m68k.M68kIcons
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub
import javax.swing.Icon
abstract class M68kMacroDefinitionMixin : StubBasedPsiElementBase<M68kMacroDefinitionStub>, M68kMacroDefinition {
constructor(node: ASTNode) : super(node)
constructor(stub: M68kMacroDefinitionStub, nodeType: IStubElementType<*, *>) : super(stub, nodeType)
override fun getPresentation(): ItemPresentation? {
return PresentationData(name, containingFile.name, getIcon(0), null)
}
override fun getIcon(flags: Int): Icon? {
return M68kIcons.MACRO_DEF
}
override fun toString(): String {
return javaClass.simpleName + "(MACRO_DEFINITION)"
}
}

View File

@ -4,6 +4,7 @@ import com.intellij.psi.PsiElement
import com.intellij.util.IncorrectOperationException
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createMacroDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createSymbolDefinition
object M68kPsiImplUtil {
@ -71,4 +72,26 @@ object M68kPsiImplUtil {
val text = element.firstChild.text
return text.startsWith('.') || text.endsWith('$')
}
// Macro Definition
@JvmStatic
fun getName(element: M68kMacroDefinition): String? = element.macroNameDefinition.firstChild.text
@JvmStatic
fun setName(element: M68kMacroDefinition, name: String): PsiElement {
val nameNode = element.macroNameDefinition
val newMacroDefinition = createMacroDefinition(element.project, name)
nameNode.replace(newMacroDefinition.firstChild)
return element
}
@JvmStatic
fun getNameIdentifier(element: M68kMacroDefinition): PsiElement = element.firstChild
// Macro Call
@JvmStatic
fun getMacroName(element: M68kMacroCall): String = element.firstChild.text
}

View File

@ -13,12 +13,13 @@ class M68kRenameInputValidator : RenameInputValidator {
override fun getPattern(): ElementPattern<out PsiElement?> = StandardPatterns.or(
PlatformPatterns.psiElement(M68kGlobalLabel::class.java),
PlatformPatterns.psiElement(M68kLocalLabel::class.java),
PlatformPatterns.psiElement(M68kSymbolDefinition::class.java)
PlatformPatterns.psiElement(M68kSymbolDefinition::class.java),
PlatformPatterns.psiElement(M68kMacroDefinition::class.java)
)
override fun isInputValid(newName: String, element: PsiElement, context: ProcessingContext): Boolean {
return when (element) {
is M68kGlobalLabel, is M68kSymbolDefinition -> SYMBOL_PATTERN.matcher(newName).matches()
is M68kGlobalLabel, is M68kSymbolDefinition, is M68kMacroDefinition -> SYMBOL_PATTERN.matcher(newName).matches()
is M68kLocalLabel -> LOCAL_LABEL_PATTERN.matcher(newName).matches()
else -> false
}

View File

@ -7,12 +7,14 @@ import com.intellij.psi.PsiPolyVariantReferenceBase
import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiSearchHelper
import com.intellij.psi.search.UsageSearchContext
import com.intellij.psi.stubs.StubIndex
import com.intellij.util.SmartList
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kNamedElement
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
@ -24,18 +26,23 @@ class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
class Resolver : ResolveCache.PolyVariantResolver<M68kGlobalLabelSymbolReference> {
override fun resolve(ref: M68kGlobalLabelSymbolReference, incompleteCode: Boolean): Array<ResolveResult> {
val refName = ref.element.symbolName
val project = ref.element.project
val targets: MutableList<PsiElement> = SmartList()
PsiSearchHelper.getInstance(project).processElementsWithWord(
{ elem, _ ->
when (elem) {
is M68kGlobalLabel, is M68kSymbolDefinition -> targets.add(elem)
}
val targets: MutableList<M68kNamedElement> = SmartList()
StubIndex.getInstance()
.processElements(M68kGlobalLabelStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java)
{
targets.add(it)
true
}, GlobalSearchScope.allScope(project),
refName, UsageSearchContext.IN_CODE, true
)
}
StubIndex.getInstance()
.processElements(M68kSymbolDefinitionStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kSymbolDefinition::class.java)
{
targets.add(it)
true
}
return targets
.map(::PsiElementResolveResult)
.toTypedArray()

View File

@ -0,0 +1,19 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.patterns.PlatformPatterns
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
class M68kMacroCallCompletionContributor : CompletionContributor() {
init {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.MACRO_INVOCATION), object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
resultSet.addAllElements(M68kLookupUtil.findAllMacroDefinitions(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
}
})
}
}

View File

@ -0,0 +1,17 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.openapi.util.TextRange
import com.intellij.psi.AbstractElementManipulator
import com.intellij.util.IncorrectOperationException
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
class M68kMacroCallElementManipulator : AbstractElementManipulator<M68kMacroCall>() {
@Throws(IncorrectOperationException::class)
override fun handleContentChange(element: M68kMacroCall, range: TextRange, newContent: String): M68kMacroCall {
val newMacroCall = M68kElementFactory.createMacroCall(element.project, newContent)
element.firstChild.replace(newMacroCall.firstChild)
return element
}
}

View File

@ -0,0 +1,49 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementResolveResult
import com.intellij.psi.PsiPolyVariantReferenceBase
import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.util.SmartList
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex
class M68kMacroReference(element: M68kMacroCall) :
PsiPolyVariantReferenceBase<M68kMacroCall>(element, TextRange(0, element.macroName.length)) {
companion object {
val INSTANCE = Resolver()
}
class Resolver : ResolveCache.PolyVariantResolver<M68kMacroReference> {
override fun resolve(ref: M68kMacroReference, incompleteCode: Boolean): Array<ResolveResult> {
val macroName = ref.element.macroName
val project = ref.element.project
val targets: MutableList<M68kMacroDefinition> = SmartList()
StubIndex.getInstance()
.processElements(M68kMacroDefinitionStubIndex.KEY, macroName, project, GlobalSearchScope.allScope(project), M68kMacroDefinition::class.java)
{
targets.add(it)
true
}
return targets
.map(::PsiElementResolveResult)
.toTypedArray()
}
}
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> =
ResolveCache.getInstance(element.project)
.resolveWithCaching(this, INSTANCE, false, incompleteCode)
override fun resolve(): PsiElement? = multiResolve(false).singleOrNull()?.element
override fun getVariants(): Array<Any> = emptyArray()
}

View File

@ -3,6 +3,7 @@ package de.platon42.intellij.plugins.m68k.refs
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.*
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
class M68kReferenceContributor : PsiReferenceContributor() {
@ -10,11 +11,13 @@ class M68kReferenceContributor : PsiReferenceContributor() {
companion object {
val localLabelReferenceProvider = LocalLabelReferenceProvider()
val globalLabelReferenceProvider = GlobalLabelSymbolReferenceProvider()
val macroReferenceProvider = MacroReferenceProvider()
}
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), localLabelReferenceProvider)
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), globalLabelReferenceProvider)
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kMacroCall::class.java), macroReferenceProvider)
}
class LocalLabelReferenceProvider : PsiReferenceProvider() {
@ -32,4 +35,9 @@ class M68kReferenceContributor : PsiReferenceContributor() {
return arrayOf(M68kGlobalLabelSymbolReference(symbolReference))
}
}
class MacroReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> =
arrayOf(M68kMacroReference(element as M68kMacroCall))
}
}

View File

@ -16,7 +16,7 @@ class M68kFindUsagesProvider : FindUsagesProvider {
override fun getWordsScanner(): WordsScanner =
DefaultWordsScanner(
M68kLexer(M68kLexerPrefs()), // FIXME Oh no! More Prefs!
TokenSet.create(M68kTypes.SYMBOLDEF, M68kTypes.GLOBAL_LABEL_DEF, M68kTypes.LOCAL_LABEL_DEF, M68kTypes.SYMBOL),
TokenSet.create(M68kTypes.SYMBOLDEF, M68kTypes.GLOBAL_LABEL_DEF, M68kTypes.LOCAL_LABEL_DEF, M68kTypes.MACRO_NAME),
TokenSet.create(M68kTypes.COMMENT),
TokenSet.create(M68kTypes.STRINGLIT, M68kTypes.DECIMAL, M68kTypes.HEXADECIMAL, M68kTypes.OCTAL, M68kTypes.BINARY),
TokenSet.EMPTY
@ -32,6 +32,8 @@ class M68kFindUsagesProvider : FindUsagesProvider {
is M68kLocalLabel -> "local label"
is M68kSymbolDefinition -> "symbol definition"
is M68kSymbolReference -> "symbol reference"
is M68kMacroDefinition -> "macro definition"
is M68kMacroCall -> "macro call"
is M68kRegister -> "register"
is M68kRefExpr -> "reference expression"
else -> ""
@ -44,6 +46,8 @@ class M68kFindUsagesProvider : FindUsagesProvider {
is M68kLocalLabel -> element.name!!
is M68kSymbolDefinition -> element.parent.text
is M68kSymbolReference -> element.symbolName
is M68kMacroDefinition -> element.macroNameDefinition.text
is M68kMacroCall -> element.macroName
is M68kRefExpr -> element.symbolReference?.symbolName ?: ""
is M68kRegister -> element.text
else -> ""

View File

@ -20,6 +20,7 @@ class M68kStructureViewElement(private val myElement: NavigatablePsiElement) : S
is M68kFile -> {
listOf(
M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedBy { it.startOffset },
M68kLookupUtil.findAllMacroDefinitions(myElement).sortedBy { it.startOffset },
M68kLookupUtil.findAllGlobalLabels(myElement).sortedBy { it.startOffset },
// M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name!! }),
// M68kLookupUtil.findAllGlobalLabels(myElement).sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name!! })

View File

@ -7,6 +7,7 @@ import com.intellij.ide.util.treeView.smartTree.Sorter
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiFile
import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
class M68kStructureViewModel(psiFile: PsiFile, editor: Editor?) :
StructureViewModelBase(psiFile, editor, M68kStructureViewElement(psiFile)), ElementInfoProvider {
@ -16,7 +17,7 @@ class M68kStructureViewModel(psiFile: PsiFile, editor: Editor?) :
}
override fun isAlwaysLeaf(element: StructureViewTreeElement): Boolean {
return element.value is M68kLocalLabel
return element.value is M68kLocalLabel || element.value is M68kMacroDefinition
}
override fun getSorters(): Array<Sorter> {

View File

@ -8,11 +8,14 @@ import com.intellij.psi.stubs.*
import com.intellij.psi.tree.ILightStubFileElementType
import de.platon42.intellij.plugins.m68k.MC68000Language.Companion.INSTANCE
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
import de.platon42.intellij.plugins.m68k.psi.impl.M68kGlobalLabelImpl
import de.platon42.intellij.plugins.m68k.psi.impl.M68kMacroDefinitionImpl
import de.platon42.intellij.plugins.m68k.psi.impl.M68kSymbolDefinitionImpl
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kGlobalLabelStubImpl
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kMacroDefinitionStubImpl
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kSymbolDefinitionStubImpl
import java.io.IOException
@ -67,5 +70,28 @@ interface M68kElementTypes {
override fun indexStub(stub: M68kSymbolDefinitionStub, sink: IndexSink) = sink.occurrence(M68kSymbolDefinitionStubIndex.KEY, stub.name!!)
}
@JvmField
val MACRO_DEFINITION: IStubElementType<M68kMacroDefinitionStub, M68kMacroDefinition> =
object : M68kStubElementType<M68kMacroDefinitionStub, M68kMacroDefinition>("MACRO_DEFINITION") {
override fun createPsi(stub: M68kMacroDefinitionStub): M68kMacroDefinition = M68kMacroDefinitionImpl(stub, this)
override fun createStub(psi: M68kMacroDefinition, parentStub: StubElement<out PsiElement>): M68kMacroDefinitionStub =
M68kMacroDefinitionStubImpl(parentStub, this, psi.name!!)
override fun createStub(tree: LighterAST, node: LighterASTNode, parentStub: StubElement<*>): M68kMacroDefinitionStub {
val idNode = LightTreeUtil.requiredChildOfType(tree, node, M68kTypes.MACRO_NAME_DEFINITION)
return M68kMacroDefinitionStubImpl(parentStub, this, LightTreeUtil.toFilteredString(tree, idNode, null))
}
@Throws(IOException::class)
override fun serialize(stub: M68kMacroDefinitionStub, dataStream: StubOutputStream) = dataStream.writeName(stub.name)
@Throws(IOException::class)
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): M68kMacroDefinitionStub =
M68kMacroDefinitionStubImpl(parentStub, this, dataStream.readName()!!)
override fun indexStub(stub: M68kMacroDefinitionStub, sink: IndexSink) = sink.occurrence(M68kMacroDefinitionStubIndex.KEY, stub.name!!)
}
}
}

View File

@ -0,0 +1,6 @@
package de.platon42.intellij.plugins.m68k.stubs
import com.intellij.psi.stubs.NamedStub
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
interface M68kMacroDefinitionStub : NamedStub<M68kMacroDefinition>

View File

@ -0,0 +1,16 @@
package de.platon42.intellij.plugins.m68k.stubs
import com.intellij.psi.stubs.StringStubIndexExtension
import com.intellij.psi.stubs.StubIndexKey
import de.platon42.intellij.plugins.m68k.M68kFileElementType
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
class M68kMacroDefinitionStubIndex : StringStubIndexExtension<M68kMacroDefinition>() {
override fun getKey(): StubIndexKey<String, M68kMacroDefinition> = KEY
override fun getVersion(): Int = M68kFileElementType.STUB_VERSION
companion object {
val KEY = StubIndexKey.createIndexKey<String, M68kMacroDefinition>("mc68000.macrodef.index")
}
}

View File

@ -10,6 +10,7 @@ object M68kStubElementTypeFactory {
return when (name) {
"GLOBAL_LABEL" -> M68kElementTypes.GLOBAL_LABEL
"SYMBOL_DEFINITION" -> M68kElementTypes.SYMBOL_DEFINITION
"MACRO_DEFINITION" -> M68kElementTypes.MACRO_DEFINITION
else -> throw RuntimeException("Unknown element type '$name'")
}
}

View File

@ -0,0 +1,13 @@
package de.platon42.intellij.plugins.m68k.stubs.impl
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.NamedStubBase
import com.intellij.psi.stubs.StubElement
import com.intellij.util.io.StringRef
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub
class M68kMacroDefinitionStubImpl : NamedStubBase<M68kMacroDefinition>, M68kMacroDefinitionStub {
constructor(parent: StubElement<*>, elementType: IStubElementType<*, *>, name: StringRef) : super(parent, elementType, name)
constructor(parent: StubElement<*>, elementType: IStubElementType<*, *>, name: String) : super(parent, elementType, name)
}

View File

@ -34,7 +34,7 @@ class M68kSyntaxHighlighter(val project: Project?) : SyntaxHighlighterBase() {
M68kTypes.MNEMONIC -> arrayOf(MNEMONIC)
M68kTypes.MACRO_TAG, M68kTypes.MACRO_END_TAG -> arrayOf(MACRO_PREPROCESSOR)
M68kTypes.MACRO_LINE -> arrayOf(MACRO_LINE)
M68kTypes.MACRO_INVOKATION -> arrayOf(MACRO_CALL)
M68kTypes.MACRO_INVOCATION -> arrayOf(MACRO_CALL)
M68kTypes.MACRO_NAME -> arrayOf(MACRO_NAME_DEF)
M68kTypes.DATA_DIRECTIVE -> arrayOf(DATA_PREPROCESSOR)
M68kTypes.OTHER_DIRECTIVE, M68kTypes.EQU -> arrayOf(OTHER_PREPROCESSOR)

View File

@ -24,15 +24,19 @@
<colorSettingsPage implementation="de.platon42.intellij.plugins.m68k.syntax.M68kColorSettingsPage"/>
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.asm.M68kMnemonicCompletionContributor"/>
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kGlobalLabelSymbolCompletionContributor"/>
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallCompletionContributor"/>
<lang.braceMatcher language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.syntax.M68kPairedBraceMatcher"/>
<lang.quoteHandler language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.M68kStringQuoteHandler"/>
<lang.findUsagesProvider language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.scanner.M68kFindUsagesProvider"/>
<lang.psiStructureViewFactory language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.structureview.M68kStructureViewFactory"/>
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference"
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kSymbolReferenceElementManipulator"/>
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kMacroCall"
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallElementManipulator"/>
<stubElementTypeHolder class="de.platon42.intellij.plugins.m68k.stubs.M68kElementTypes"/>
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex"/>
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex"/>
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex"/>
<psi.referenceContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>

View File

@ -23,6 +23,11 @@ internal class MacroCallTest : AbstractParsingTest() {
testGoodSyntax(testCase, " PUSHM d0/d3/d5-d7/a0-a2/a4-a6 ; save a couple of registers\n")
}
@Test
internal fun call_with_label(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(testCase, "label FOOBAR narf ; wut?\n")
}
@Test
internal fun putmsg_call_with_specially_bracketed_parameters(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
// FIXME this doesn't work as intended...

View File

@ -0,0 +1,32 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.LightCodeInsightExtension
import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@TestDataPath("src/test/resources/references")
@TestDataSubPath("completion")
@ExtendWith(LightCodeInsightExtension::class)
internal class M68kMacroCallCompletionContributorTest : AbstractM68kTest() {
@Test
internal fun completion_shows_mnemonics_and_macros(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.configureByText(
"completeme.asm", """
noppy MACRO
ENDM
no<caret>
"""
)
myFixture.completeBasic()
assertThat(myFixture.lookupElementStrings).containsExactlyInAnyOrder("nop", "not", "noppy")
}
}

View File

@ -8,10 +8,7 @@ import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
import de.platon42.intellij.plugins.m68k.psi.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ -71,4 +68,22 @@ internal class M68kReferenceContributorTest : AbstractM68kTest() {
myFixture.checkResultByFile("symbol_assignment_after_rename.asm")
}
@Test
@TestDataSubPath("macros")
internal fun reference_to_macro_can_be_renamed(@MyFixture myFixture: CodeInsightTestFixture) {
val file = myFixture.configureByFile("macros.asm")
val elementAtCaret = myFixture.elementAtCaret
assertThat(elementAtCaret).isInstanceOf(M68kMacroDefinition::class.java)
val macroDef = elementAtCaret as M68kMacroDefinition
assertThat(macroDef.macroNameDefinition.text).isEqualTo("PUTMSG")
myFixture.renameElementAtCaret("PRINTF")
val reference = file.findReferenceAt(myFixture.editor.caretModel.offset)!!
assertThat(reference).isInstanceOf(M68kMacroReference::class.java)
assertThat(reference.variants).isEmpty()
myFixture.checkResultByFile("macros_after_rename.asm")
}
}

View File

@ -24,6 +24,8 @@ internal class M68kStructureViewTest : AbstractM68kTest() {
PIC_WIDTH
PIC_HEIGHT
DEBUG_LEVEL
BLTHOGON
BLTHOGOFF
entry
-init
.looph

View File

@ -2,11 +2,13 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('PUSHM')
PsiElement(M68kTokenType.MACRO_INVOCATION)('PUSHM')
PsiWhiteSpace(' ')
PsiElement(M68kTokenType.STRINGLIT)('d0')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0')
PsiElement(M68kTokenType.SEPARATOR)(',')
PsiElement(M68kTokenType.STRINGLIT)('d0')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('hey comment')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -2,12 +2,14 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('PUSHM')
PsiElement(M68kTokenType.MACRO_INVOCATION)('PUSHM')
PsiWhiteSpace(' ')
PsiElement(M68kTokenType.STRINGLIT)('d0')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0')
PsiElement(M68kTokenType.SEPARATOR)(',')
PsiWhiteSpace(' ')
PsiElement(M68kTokenType.STRINGLIT)('d0')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('; hey comment')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -2,5 +2,5 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
PsiErrorElement:'.' unexpected
PsiElement(BAD_CHARACTER)('.')
PsiElement(M68kTokenType.MACRO_INVOKATION)('local_label')
PsiElement(M68kTokenType.MACRO_INVOCATION)('local_label')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -2,6 +2,7 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('local_label')
PsiElement(M68kTokenType.STRINGLIT)('$')
PsiElement(M68kTokenType.MACRO_INVOCATION)('local_label')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('$')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -2,9 +2,11 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('COPIMOVE')
PsiElement(M68kTokenType.MACRO_INVOCATION)('COPIMOVE')
PsiWhiteSpace(' ')
PsiElement(M68kTokenType.STRINGLIT)('(3<<0)|(3<<3)|(1<<6)')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('(3<<0)|(3<<3)|(1<<6)')
PsiElement(M68kTokenType.SEPARATOR)(',')
PsiElement(M68kTokenType.STRINGLIT)('bplcon2')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('bplcon2')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -0,0 +1,13 @@
Assembly File: a.asm
M68kStatementImpl(STATEMENT)
M68kGlobalLabelImpl(GLOBAL_LABEL)
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('label')
PsiWhiteSpace(' ')
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOCATION)('FOOBAR')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('narf')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('; wut?')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -2,9 +2,10 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('PUSHM')
PsiElement(M68kTokenType.MACRO_INVOCATION)('PUSHM')
PsiWhiteSpace(' ')
PsiElement(M68kTokenType.STRINGLIT)('d0/d3/d5-d7/a0-a2/a4-a6')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0/d3/d5-d7/a0-a2/a4-a6')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('; save a couple of registers')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -2,17 +2,23 @@ Assembly File: a.asm
PsiWhiteSpace('\t')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('PUTMSG')
PsiElement(M68kTokenType.MACRO_INVOCATION)('PUTMSG')
PsiWhiteSpace(' ')
PsiElement(M68kTokenType.STRINGLIT)('10')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('10')
PsiElement(M68kTokenType.SEPARATOR)(',')
PsiElement(M68kTokenType.STRINGLIT)('<"%s has left the building at %d:%d",10,'Yup!'>')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('<"%s has left the building at %d:%d",10,'Yup!'>')
PsiElement(M68kTokenType.SEPARATOR)(',')
PsiElement(M68kTokenType.STRINGLIT)('a0')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('a0')
PsiElement(M68kTokenType.SEPARATOR)(',')
PsiElement(M68kTokenType.STRINGLIT)('$42(a1')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('$42(a1')
PsiElement(M68kTokenType.SEPARATOR)(',')
PsiElement(M68kTokenType.STRINGLIT)('d0.w)')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('d0.w)')
PsiElement(M68kTokenType.SEPARATOR)(',')
PsiElement(M68kTokenType.STRINGLIT)('#42')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('#42')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -2,5 +2,5 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kMacroCallImpl(MACRO_CALL)
PsiElement(M68kTokenType.MACRO_INVOKATION)('BLT_HOG_ON')
PsiElement(M68kTokenType.MACRO_INVOCATION)('BLT_HOG_ON')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -0,0 +1,13 @@
PUTMSG MACRO
printf
ENDM
UAEExitWarp MACRO
ENDM
main PUTM<caret>SG 10,<"Enter MAIN!">,d0
rts
exit PUTMSG 10,<"Exit!">,d0
illegal
rts

View File

@ -0,0 +1,13 @@
PRINTF MACRO
printf
ENDM
UAEExitWarp MACRO
ENDM
main PRINTF 10,<"Enter MAIN!">,d0
rts
exit PRINTF 10,<"Exit!">,d0
illegal
rts

View File

@ -2,6 +2,14 @@ PIC_WIDTH = 320
PIC_HEIGHT equ 256
DEBUG_LEVEL set 10
BLTHOGON MACRO
foo
ENDM
BLTHOGOFF MACRO
bar
ENDM
entry:
bsr init
bsr main