Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62f7f13323 | ||
|
|
c4051a0377 | ||
|
|
a03de6c394 | ||
|
|
1bff1a12c2 | ||
|
|
665947827b | ||
|
|
3bb6165a58 | ||
|
|
89bd964fe7 | ||
|
|
0cb90ff8d7 | ||
|
|
431caf64fd | ||
|
|
a3f7ddb4f7 | ||
|
|
593719043e | ||
|
|
e0cdfef42b | ||
|
|
8d7977927f | ||
|
|
ddf78ec210 |
@@ -10,8 +10,8 @@ This plugin delivers support for MC68000 assembly language files ([VAsm](http://
|
|||||||
|
|
||||||
It adds a language parser with syntax highlighting, referencing and refactoring support, and a few more features.
|
It adds a language parser with syntax highlighting, referencing and refactoring support, and a few more features.
|
||||||
|
|
||||||
I'm an Amiga retro democoder, and the lack of a plugin for M68k was the motivation to write one. Also, diving deep into custom language plugins has a steep
|
I'm an Amiga retro democoder (among other things), and the lack of a plugin for M68k was the motivation to write one. Also, diving deep into custom language
|
||||||
learning curve.
|
plugins has a steep learning curve.
|
||||||
|
|
||||||
When I started the plugin in July 2021, I was not aware of the [M68k plugin efforts by Jetbrains employee Yann Cébron](https://github.com/YannCebron/m68kplugin)
|
When I started the plugin in July 2021, I was not aware of the [M68k plugin efforts by Jetbrains employee Yann Cébron](https://github.com/YannCebron/m68kplugin)
|
||||||
who has been working on the same topic for quite some time. At the time of writing, his plugin however, has not been release yet. Nevertheless, it has a lot of
|
who has been working on the same topic for quite some time. At the time of writing, his plugin however, has not been release yet. Nevertheless, it has a lot of
|
||||||
@@ -19,17 +19,17 @@ awesome features and is pretty advanced. Check it out. You can install both plug
|
|||||||
|
|
||||||
Big kudos to Yann -- a few features were _inspired_ by his code.
|
Big kudos to Yann -- a few features were _inspired_ by his code.
|
||||||
|
|
||||||
My plugin, on the other hand, is still pretty basic and is the result of a few weeks of work. I released a really early first version it because I think it's "
|
My plugin, on the other hand, is still pretty basic and is the result of a few weeks of work. I released the first versions because I think it's "good enough"
|
||||||
good enough" to get started, and I can return to demo coding with its current state.
|
to get started, and I can return to demo coding with its current state.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Parser / Lexer for MC68000 (yes, only 68000 right now!) assembly language files in VAsm / DevPac style
|
- Parser / Lexer for MC68000 (yes, only 68000 right now!) assembly language files in VAsm / DevPac style
|
||||||
- Inspection for validating the syntax of the 68000 ISA.
|
- Validates the assembly syntax against the 68000 ISA.
|
||||||
- Syntax highlighting and Color Settings Page (you should really modify the color settings to your likings!)
|
- Syntax highlighting and Color Settings Page (you should really modify the color settings to your likings!)
|
||||||
- Mnemonics code completion
|
- Mnemonics code completion
|
||||||
- Symbols / Labels / Macros code completion
|
- Symbols / labels / macros code completion
|
||||||
- References / Refactoring support for local and global labels, symbol assignments, and macros.
|
- References / refactoring support for local and global labels, symbol assignments, and macros.
|
||||||
- Simple register usage flow (hover over register or press F1 for full flow)
|
- Simple register usage flow (hover over register or press F1 for full flow)
|
||||||
- Brace matching
|
- Brace matching
|
||||||
- Quote handler
|
- Quote handler
|
||||||
@@ -39,7 +39,10 @@ good enough" to get started, and I can return to demo coding with its current st
|
|||||||
|
|
||||||
### Inspections
|
### Inspections
|
||||||
|
|
||||||
#### M68kSyntaxInspection - Assembly instruction validity
|
The plugin provides a few inspections for code analysis. An error or warning can be suppressed by placing a `; suppress <InspectionName>` comment either on an
|
||||||
|
end of line comment behind the statement or in a full line comment above the statement.
|
||||||
|
|
||||||
|
#### M68kSyntax - Assembly instruction validity
|
||||||
|
|
||||||
Checks the validity of the current instruction. If an instruction is not recognized, you may get one of the following errors:
|
Checks the validity of the current instruction. If an instruction is not recognized, you may get one of the following errors:
|
||||||
|
|
||||||
@@ -54,7 +57,7 @@ Checks the validity of the current instruction. If an instruction is not recogni
|
|||||||
- Operation size _(.b,.w,.l)_ unsupported for _mnemonic_
|
- Operation size _(.b,.w,.l)_ unsupported for _mnemonic_
|
||||||
- Operation size _(.b,.w,.l)_ unsupported (should be _(.b,.w,.l)_)
|
- Operation size _(.b,.w,.l)_ unsupported (should be _(.b,.w,.l)_)
|
||||||
|
|
||||||
#### M68kDeadWriteInspection - Dead writes to registers
|
#### M68kDeadWrite - Dead writes to registers
|
||||||
|
|
||||||
This inspection looks at register writes and tries to find instructions that renders a write moot because it was overwritten by another instruction before
|
This inspection looks at register writes and tries to find instructions that renders a write moot because it was overwritten by another instruction before
|
||||||
anything useful was done with it.
|
anything useful was done with it.
|
||||||
@@ -65,7 +68,7 @@ Analysis is aborted at global labels, flow control instructions, directives
|
|||||||
The inspection tries to take condition code changing into account and puts out a weak warning if the statement merely changes condition codes before the
|
The inspection tries to take condition code changing into account and puts out a weak warning if the statement merely changes condition codes before the
|
||||||
contents of the register are overwritten. In this case, it is sometimes better to replace `move` by `tst`.
|
contents of the register are overwritten. In this case, it is sometimes better to replace `move` by `tst`.
|
||||||
|
|
||||||
#### M68kUnexpectedConditionalInstructionInspection - Unaffected condition codes before conditional instruction
|
#### M68kUnexpectedConditionalInstruction - Unaffected condition codes before conditional instruction
|
||||||
|
|
||||||
Especially for novice coders, it is not clear that some instructions do not affect the condition codes for a subsequent condition branch or `scc` instruction.
|
Especially for novice coders, it is not clear that some instructions do not affect the condition codes for a subsequent condition branch or `scc` instruction.
|
||||||
`movea`, `adda` and `suba` come to my mind.
|
`movea`, `adda` and `suba` come to my mind.
|
||||||
@@ -75,13 +78,22 @@ The inspection will report such suspicious instruction sequences.
|
|||||||
However, this does not need to be a programming error. Advanced coders sometimes make use of the fact that instructions do not change condition codes and thus
|
However, this does not need to be a programming error. Advanced coders sometimes make use of the fact that instructions do not change condition codes and thus
|
||||||
optimize the order of execution.
|
optimize the order of execution.
|
||||||
|
|
||||||
|
#### M68kUnresolvedReference - Unresolved label/symbol/macro reference
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
### Documentation provider
|
### Documentation provider
|
||||||
|
|
||||||
#### M68kSymbolDefinitionDocumentationProvider
|
#### M68kSymbolDefinition
|
||||||
|
|
||||||
Provides the assigned value of a `=`, `set` or `equ` symbol definition when hovering over a symbol.
|
Provides the assigned value of a `=`, `set` or `equ` symbol definition when hovering over a symbol.
|
||||||
|
|
||||||
#### M68kRegisterFlowDocumentationProvider
|
#### M68kGlobalLabel
|
||||||
|
|
||||||
|
Shows the comments above the label and if the first statement after the label is a directive like `include` or `dc.b`, shows it, too.
|
||||||
|
|
||||||
|
#### M68kRegisterFlow
|
||||||
|
|
||||||
When hovering over or placing the cursor at a data or address register, the documentation will scan through the instructions backwards and forwards and will
|
When hovering over or placing the cursor at a data or address register, the documentation will scan through the instructions backwards and forwards and will
|
||||||
show all read, changes of the register contents. It does this until an instruction is found that defines (sets) the contents of the register
|
show all read, changes of the register contents. It does this until an instruction is found that defines (sets) the contents of the register
|
||||||
@@ -92,7 +104,7 @@ The analysis ignores all code flow instructions and might be inaccurate for bran
|
|||||||
The documentation will search up to 100 instructions in each direction, but only four when hovering over the register
|
The documentation will search up to 100 instructions in each direction, but only four when hovering over the register
|
||||||
(so if you need the whole analysis, use the documentation window).
|
(so if you need the whole analysis, use the documentation window).
|
||||||
|
|
||||||
#### M68kInstructionDocumentationProvider
|
#### M68kInstruction
|
||||||
|
|
||||||
When hovering over a mnemonic, it will show a short description of the assembly instruction.
|
When hovering over a mnemonic, it will show a short description of the assembly instruction.
|
||||||
|
|
||||||
@@ -104,13 +116,13 @@ If the current statement has no valid syntax, the instruction details of all mat
|
|||||||
## Known issues
|
## Known issues
|
||||||
|
|
||||||
- `Find Usages` always shows _"Unclassified"_ though it shouldn't (?)
|
- `Find Usages` always shows _"Unclassified"_ though it shouldn't (?)
|
||||||
|
- `END` detection was breaking parsing, so this is disabled for now until I find a working solution.
|
||||||
- Macro invocations are not yet evaluated, thus no referencing to symbols defined via macros (e.g. `STRUCT`).
|
- Macro invocations are not yet evaluated, thus no referencing to symbols defined via macros (e.g. `STRUCT`).
|
||||||
- No support for includes. Scoping is for global symbols and labels is currently the whole project.
|
- Scoping for global symbols and labels is currently the whole project.
|
||||||
- No support for register replacement (e.g. registers replaced by `EQUR` or `EQURL` will cause syntax errors)
|
- No support for register replacement (e.g. registers replaced by `EQUR` or `EQURL` will cause syntax errors)
|
||||||
- While the Lexer supports the -spaces option (where a space introduces a comment), this cannot be configured yet (default is off).
|
- While the Lexer supports the -spaces option (where a space introduces a comment), this cannot be configured yet (default is off).
|
||||||
- No support for other processor instructions, FPU or 68020+ address modes.
|
- No support for other processor instructions, FPU or 68020+ address modes.
|
||||||
- Unit Test coverage is not as good as it could be (ahem).
|
- Unit Test coverage is not as good as it could be (ahem).
|
||||||
- `opt` keyword needs special treatment and will currently show a parsing error.
|
|
||||||
- Missing but planned features:
|
- Missing but planned features:
|
||||||
- Macro evaluation on invocation
|
- Macro evaluation on invocation
|
||||||
- Folding
|
- Folding
|
||||||
@@ -133,17 +145,36 @@ It is probably the only plugin (besides [Cajon](https://github.com/chrisly42/caj
|
|||||||
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
|
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).
|
make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for your projects (with attribution).
|
||||||
|
|
||||||
## Private TODO list
|
## Feedback
|
||||||
|
|
||||||
- code completion suggestion for unresolved local labels, global labels and symbols
|
I guess there are currently over 500 users of this plugin and while I wrote this mainly for myself, I'm only doing this in my spare time.
|
||||||
- support `include` directive
|
|
||||||
- support `opt` directive
|
Feedback and [rating](https://plugins.jetbrains.com/plugin/17268-mc68000-assembly-language-support/reviews)
|
||||||
- suppression support via comments
|
are appreciated. It really is keeping me motivated to continue development.
|
||||||
- inspection: Unresolved local label
|
|
||||||
- inspection: Unresolved macro
|
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### V0.7 (26-Sep-21)
|
||||||
|
|
||||||
|
- Bugfix: `btst` with pc-relative and weird immediate mode was missing (courtesy of Yann).
|
||||||
|
- Bugfix: `movem` with pc-relative mode was missing for weird immediate mode (courtesy of Yann).
|
||||||
|
- Bugfix: Special registers for address mode matching only worked with lower case register names (courtesy of Yann).
|
||||||
|
- Enhancement: Assembler syntax with implicit immediate 1 for shifts and rotations no longer cause syntax errors (courtesy of Yann).
|
||||||
|
- Enhancement: Documentation for instruction with special register shows specific register expected.
|
||||||
|
- New: Added documentation provider info for global labels. Shows directives and comments above.
|
||||||
|
- Bugfix: Fixed BNF for labels with preprocessor statements.
|
||||||
|
- Disabled: `END` detection was breaking parsing, causing havoc.
|
||||||
|
|
||||||
|
### V0.6 (09-Aug-21)
|
||||||
|
|
||||||
|
- Enhancement: `opt` and several other directives (`printt`, `fail` etc.) no longer causes a syntax error when unquoted.
|
||||||
|
- Enhancement: `include`, `incdir` and `incbin` and `output` with `<pathname>` quotes no longer cause syntax error.
|
||||||
|
- New: Files in `include` directives can be referenced and renamed/refactored.
|
||||||
|
- New: Code completion for local label definitions, suggesting undefined labels already referenced.
|
||||||
|
- New: Added inspection suppression possibility and quickfix.
|
||||||
|
- New: Added inspection for unresolved symbols, macros and labels.
|
||||||
|
- Enhancement: 'END' directive stops parsing.
|
||||||
|
|
||||||
### V0.5 (06-Aug-21)
|
### V0.5 (06-Aug-21)
|
||||||
|
|
||||||
- Bugfix: `movem` ISA was wrong regarding the `movem.w <ea>,<registerlist>` (sign extends registers).
|
- Bugfix: `movem` ISA was wrong regarding the `movem.w <ea>,<registerlist>` (sign extends registers).
|
||||||
@@ -175,7 +206,7 @@ make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.
|
|||||||
- Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
|
- Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
|
||||||
- New: Macro definition refactoring and find usages support.
|
- New: Macro definition refactoring and find usages support.
|
||||||
- Enhancement: Structural View also shows macro definitions.
|
- Enhancement: Structural View also shows macro definitions.
|
||||||
- Bugfix: Missing REPT and ENDR assembler directives added.
|
- Bugfix: Missing `REPT` and `ENDR` assembler directives added.
|
||||||
- Cosmetics: Changed or added some icons at various places.
|
- Cosmetics: Changed or added some icons at various places.
|
||||||
- Performance: Reference search for global labels and symbols now uses stub index.
|
- Performance: Reference search for global labels and symbols now uses stub index.
|
||||||
- Compatibility: Restored compatibility with IDE versions < 2021.1.
|
- Compatibility: Restored compatibility with IDE versions < 2021.1.
|
||||||
|
|||||||
+20
-33
@@ -1,13 +1,13 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'org.jetbrains.intellij' version '1.1.3'
|
id 'org.jetbrains.intellij' version '1.1.6'
|
||||||
id 'org.jetbrains.kotlin.jvm' version '1.5.21'
|
id 'org.jetbrains.kotlin.jvm' version '1.5.21'
|
||||||
id 'jacoco'
|
id 'jacoco'
|
||||||
id 'com.github.kt3k.coveralls' version '2.11.0'
|
id 'com.github.kt3k.coveralls' version '2.12.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'de.platon42'
|
group = 'de.platon42'
|
||||||
version = '0.5'
|
version = '0.7'
|
||||||
sourceCompatibility = "1.8"
|
sourceCompatibility = "1.8"
|
||||||
targetCompatibility = "1.8"
|
targetCompatibility = "1.8"
|
||||||
|
|
||||||
@@ -22,9 +22,9 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
||||||
testImplementation "org.assertj:assertj-core:3.20.2"
|
testImplementation "org.assertj:assertj-core:3.21.0"
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.0-M1'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
|
||||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0-M1'
|
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-test"
|
testImplementation "org.jetbrains.kotlin:kotlin-test"
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-reflect"
|
testImplementation "org.jetbrains.kotlin:kotlin-reflect"
|
||||||
// testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
|
// testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
|
||||||
@@ -42,45 +42,32 @@ compileTestKotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
intellij {
|
intellij {
|
||||||
setVersion("2021.2") // LATEST-EAP-SNAPSHOT
|
setVersion("2021.2.2") // LATEST-EAP-SNAPSHOT
|
||||||
setUpdateSinceUntilBuild(false)
|
setUpdateSinceUntilBuild(false)
|
||||||
// setPlugins(["com.intellij.java"])
|
// setPlugins(["com.intellij.java"])
|
||||||
}
|
}
|
||||||
|
|
||||||
runPluginVerifier {
|
runPluginVerifier {
|
||||||
ideVersions = ["IC-203.6682.168", "IC-212.4746.92", // 2020.3 - 2021.2
|
ideVersions = ["IC-203.6682.168", "IC-212.5284.40", // 2020.3 - 2021.2.2
|
||||||
"CL-203.5981.166", "CL-203.8084.11", // 2020.3
|
"CL-203.5981.166", "CL-203.8084.11", // 2020.3
|
||||||
"CL-211.6693.114", "CL-211.7628.27", // 2021.1
|
"CL-211.6693.114", "CL-211.7628.27", // 2021.1
|
||||||
"CL-212.4746.93"] // 2021.2
|
"CL-212.4746.93", "CL-212.5284.51"] // 2021.2 - 2021.2.2
|
||||||
downloadDir = System.getProperty("user.home") + "/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea"
|
downloadDir = System.getProperty("user.home") + "/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/verifier"
|
||||||
}
|
}
|
||||||
|
|
||||||
patchPluginXml {
|
patchPluginXml {
|
||||||
setChangeNotes("""
|
setChangeNotes("""
|
||||||
<h4>V0.5 (06-Aug-21)</h4>
|
<p>I still got zero feedback and zero <a href="https://plugins.jetbrains.com/plugin/17268-mc68000-assembly-language-support/reviews">ratings</a> :-(</p>
|
||||||
|
<h4>V0.7 (26-Sep-21)</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Bugfix: movem ISA was wrong regarding movem.w <ea>,<registerlist> (sign extends registers).
|
<li>Bugfix: 'btst' with pc-relative and weird immediate mode was missing (courtesy of Yann).
|
||||||
<li>Cosmetics: Changed Register Flow Documentation wording from 'reads' to 'uses' and from 'modifies' to 'changes'.
|
<li>Bugfix: 'movem' with pc-relative mode was missing for weird immediate mode (courtesy of Yann).
|
||||||
<li>Bugfix: Minor fix for `andi/eori/ori to ccr` which were not byte sized in ISA.
|
<li>Bugfix: Special registers for address mode matching only worked with lower case register names (courtesy of Yann).
|
||||||
<li>Bugfix: Added alternate condition code tests HS (=CC) and LO (=CS).
|
<li>Enhancement: Assembler syntax with implicit immediate 1 for shifts and rotations no longer cause syntax errors (courtesy of Yann).
|
||||||
<li>Performance: Optimized mnemonic lookup.
|
<li>Enhancement: Documentation for instruction with special register shows specific register expected.
|
||||||
<li>Enhancement: Reworked Instruction Documentation provider, now shows condition codes.
|
<li>New: Added documentation provider info for global labels. Shows directives and comments above.
|
||||||
<li>Bugfix: In ISA exg is no longer treated as setting a definitive value.
|
<li>Bugfix: Fixed BNF for labels with preprocessor statements.
|
||||||
<li>New: Added inspection to find dead writes to registers!
|
<li>Disabled: 'END' detection was breaking parsing, causing havoc.
|
||||||
<li>New: Added inspection to warn about unexpected condition code unaffecting instructions before conditional instructions.
|
|
||||||
</ul>
|
|
||||||
<h4>V0.4 (03-Aug-21)</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Notice: Due to major new API use, this plugin no longer works on IDEs >=2019.3.1, but rather requires >=2020.3.
|
|
||||||
<li>Enhancement: Added Structure View filters.
|
|
||||||
<li>New: Added inspection to validate the correctness of a MC68000 instruction regarding operation size and address modes.
|
|
||||||
<li>Bugfix: Added several missing assembler directives (opt, machine, etc.).
|
|
||||||
<li>Bugfix: Uppercase hexadecimal literals were not parsed (JFlex bug?).
|
|
||||||
<li>Bugfix: Interpretation of register lists was wrong in BNF.
|
|
||||||
<li>New: Added Documentation Provider for symbol definitions (shows assigned declaration).
|
|
||||||
<li>New: Added Documentation Provider for mnemonics (simple version, generated out of ISA information).
|
|
||||||
<li>Bugfix: Macro definitions with colons and without space supported (as found in P61a source).
|
|
||||||
<li>New: When asking for documentation on registers, a code flow analysis is done. Cool stuff!
|
|
||||||
</ul>
|
</ul>
|
||||||
<p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p>
|
<p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p>
|
||||||
""")
|
""")
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class _M68kLexer implements FlexLexer {
|
|||||||
public static final int ASSIGNMENT = 12;
|
public static final int ASSIGNMENT = 12;
|
||||||
public static final int EXPR = 14;
|
public static final int EXPR = 14;
|
||||||
public static final int EXPR_OP = 16;
|
public static final int EXPR_OP = 16;
|
||||||
public static final int MACROCALL = 18;
|
public static final int PLAINPARAMS = 18;
|
||||||
public static final int WAITEOL = 20;
|
public static final int WAITEOL = 20;
|
||||||
public static final int MACRODEF = 22;
|
public static final int MACRODEF = 22;
|
||||||
public static final int MACROLINE = 24;
|
public static final int MACROLINE = 24;
|
||||||
@@ -194,23 +194,23 @@ public class _M68kLexer implements FlexLexer {
|
|||||||
private static final int[] ZZ_ACTION = zzUnpackAction();
|
private static final int[] ZZ_ACTION = zzUnpackAction();
|
||||||
|
|
||||||
private static final String ZZ_ACTION_PACKED_0 =
|
private static final String ZZ_ACTION_PACKED_0 =
|
||||||
"\17\0\1\1\2\2\1\3\1\4\1\1\1\5\1\6" +
|
"\17\0\1\1\2\2\1\3\1\4\1\5\1\6\1\7" +
|
||||||
"\1\7\1\10\1\1\1\7\2\11\1\7\1\10\1\12" +
|
"\1\10\1\11\1\1\1\10\2\12\1\10\1\11\1\13" +
|
||||||
"\1\13\1\14\1\1\1\15\1\16\1\17\4\16\1\1" +
|
"\1\14\1\15\1\1\1\16\1\17\1\20\4\17\1\1" +
|
||||||
"\1\16\5\1\1\20\1\21\1\22\1\23\1\24\1\25" +
|
"\1\17\5\1\1\21\1\22\1\23\1\24\1\25\1\26" +
|
||||||
"\1\26\1\27\1\30\1\31\2\16\1\32\1\33\1\34" +
|
"\1\27\1\30\1\31\1\32\2\17\1\33\1\34\1\35" +
|
||||||
"\1\35\1\36\1\37\1\40\1\41\1\42\1\43\1\44" +
|
"\1\36\1\37\1\40\1\41\1\42\1\43\1\44\1\45" +
|
||||||
"\1\45\1\46\1\47\1\42\1\50\2\1\1\51\1\16" +
|
"\1\46\1\47\1\50\1\43\1\51\2\1\1\52\1\17" +
|
||||||
"\1\52\1\11\4\52\1\53\1\11\2\54\2\55\1\56" +
|
"\1\53\1\12\4\53\1\54\1\12\2\55\2\56\1\57" +
|
||||||
"\1\57\3\60\1\57\1\60\1\0\1\4\1\61\2\62" +
|
"\1\60\3\61\1\60\1\61\1\0\1\4\1\62\2\63" +
|
||||||
"\1\63\3\0\1\7\1\64\1\65\1\66\1\67\1\70" +
|
"\1\64\3\0\1\10\1\65\1\66\1\67\1\70\1\71" +
|
||||||
"\1\71\1\16\1\72\1\73\1\16\1\74\1\75\2\0" +
|
"\1\72\1\17\1\73\1\74\1\17\1\75\1\76\2\0" +
|
||||||
"\1\76\4\0\1\77\1\16\1\32\1\100\1\101\1\102" +
|
"\1\77\4\0\1\100\1\17\1\33\1\101\1\102\1\103" +
|
||||||
"\1\103\1\104\1\105\1\106\3\0\1\52\1\0\1\52" +
|
"\1\104\1\105\1\106\1\107\3\0\1\53\1\0\1\53" +
|
||||||
"\1\0\1\52\1\0\1\52\1\55\1\57\3\0\1\4" +
|
"\1\0\1\53\1\0\1\53\1\56\1\60\3\0\1\4" +
|
||||||
"\1\62\1\63\1\7\1\107\1\7\1\110\1\111\1\112" +
|
"\1\63\1\64\1\10\1\110\1\10\1\111\1\112\1\113" +
|
||||||
"\1\113\1\0\1\52\3\0\1\55\1\57\3\0\1\7" +
|
"\1\114\1\0\1\53\3\0\1\56\1\60\3\0\1\10" +
|
||||||
"\1\55\1\57\2\0\1\114\1\115\1\116\1\0\1\117";
|
"\1\56\1\60\2\0\1\115\1\116\1\117\1\0\1\120";
|
||||||
|
|
||||||
private static int[] zzUnpackAction() {
|
private static int[] zzUnpackAction() {
|
||||||
int[] result = new int[184];
|
int[] result = new int[184];
|
||||||
@@ -624,11 +624,11 @@ public class _M68kLexer implements FlexLexer {
|
|||||||
/**
|
/**
|
||||||
* Refills the input buffer.
|
* Refills the input buffer.
|
||||||
*
|
*
|
||||||
* @return {@code false}, iff there was new input.
|
* @return {@code false}, iff there was NO new input.
|
||||||
* @throws java.io.IOException if any I/O-Error occurs
|
* @throws java.io.IOException if any I/O-Error occurs
|
||||||
*/
|
*/
|
||||||
private boolean zzRefill() throws java.io.IOException {
|
private boolean zzRefill() throws java.io.IOException {
|
||||||
return true;
|
return !zzAtEOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -814,14 +814,14 @@ public class _M68kLexer implements FlexLexer {
|
|||||||
return BAD_CHARACTER;
|
return BAD_CHARACTER;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 80:
|
case 81:
|
||||||
break;
|
break;
|
||||||
case 2: {
|
case 2: {
|
||||||
yybegin(YYINITIAL);
|
yybegin(YYINITIAL);
|
||||||
return WHITE_SPACE;
|
return WHITE_SPACE;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 81:
|
case 82:
|
||||||
break;
|
break;
|
||||||
case 3: {
|
case 3: {
|
||||||
yybegin(NOSOL);
|
yybegin(NOSOL);
|
||||||
@@ -829,7 +829,7 @@ public class _M68kLexer implements FlexLexer {
|
|||||||
return WHITE_SPACE;
|
return WHITE_SPACE;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 82:
|
case 83:
|
||||||
break;
|
break;
|
||||||
case 4: {
|
case 4: {
|
||||||
yybegin(INSTRPART);
|
yybegin(INSTRPART);
|
||||||
@@ -838,22 +838,30 @@ public class _M68kLexer implements FlexLexer {
|
|||||||
return GLOBAL_LABEL_DEF;
|
return GLOBAL_LABEL_DEF;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 83:
|
|
||||||
break;
|
|
||||||
case 5: {
|
|
||||||
yybegin(YYINITIAL);
|
|
||||||
return COMMENT;
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
case 84:
|
case 84:
|
||||||
break;
|
break;
|
||||||
case 6: {
|
case 5: {
|
||||||
return WHITE_SPACE;
|
yybegin(INSTRPART);
|
||||||
|
eatOneWhitespace = false;
|
||||||
|
return LOCAL_LABEL_DEF;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 85:
|
case 85:
|
||||||
break;
|
break;
|
||||||
|
case 6: {
|
||||||
|
yybegin(YYINITIAL);
|
||||||
|
return COMMENT;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
case 86:
|
||||||
|
break;
|
||||||
case 7: {
|
case 7: {
|
||||||
|
return WHITE_SPACE;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
case 87:
|
||||||
|
break;
|
||||||
|
case 8: {
|
||||||
if (isAsmMnemonicWithSize(yytext())) {
|
if (isAsmMnemonicWithSize(yytext())) {
|
||||||
yybegin(ASMINSTR);
|
yybegin(ASMINSTR);
|
||||||
yypushback(2);
|
yypushback(2);
|
||||||
@@ -863,10 +871,15 @@ public class _M68kLexer implements FlexLexer {
|
|||||||
yybegin(ASMINSTR);
|
yybegin(ASMINSTR);
|
||||||
return MNEMONIC;
|
return MNEMONIC;
|
||||||
}
|
}
|
||||||
|
//if(isEndDirective(yytext())) { yybegin(YYINITIAL); zzAtEOF = true; return null; }
|
||||||
if (isDataDirective(yytext())) {
|
if (isDataDirective(yytext())) {
|
||||||
startExpr(EXPR, EXPR_OP);
|
startExpr(EXPR, EXPR_OP);
|
||||||
return DATA_DIRECTIVE;
|
return DATA_DIRECTIVE;
|
||||||
}
|
}
|
||||||
|
if (isPlainDirective(yytext())) {
|
||||||
|
yybegin(PLAINPARAMS);
|
||||||
|
return OTHER_DIRECTIVE;
|
||||||
|
}
|
||||||
if (isOtherDirective(yytext())) {
|
if (isOtherDirective(yytext())) {
|
||||||
startExpr(EXPR, EXPR_OP);
|
startExpr(EXPR, EXPR_OP);
|
||||||
return OTHER_DIRECTIVE;
|
return OTHER_DIRECTIVE;
|
||||||
@@ -874,498 +887,498 @@ public class _M68kLexer implements FlexLexer {
|
|||||||
return handleMacroMode(this);
|
return handleMacroMode(this);
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 86:
|
|
||||||
break;
|
|
||||||
case 8: {
|
|
||||||
return handleMacroMode(this);
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
case 87:
|
|
||||||
break;
|
|
||||||
case 9: {
|
|
||||||
yybegin(YYINITIAL);
|
|
||||||
return EOL;
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
case 88:
|
case 88:
|
||||||
break;
|
break;
|
||||||
case 10: {
|
case 9: {
|
||||||
return COLON;
|
return handleMacroMode(this);
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 89:
|
case 89:
|
||||||
break;
|
break;
|
||||||
case 11: {
|
case 10: {
|
||||||
yybegin(WAITEOL);
|
yybegin(YYINITIAL);
|
||||||
return COMMENT;
|
return EOL;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 90:
|
case 90:
|
||||||
break;
|
break;
|
||||||
case 12: {
|
case 11: {
|
||||||
startExpr(ASMOPS, ASMOPS_OP);
|
return COLON;
|
||||||
return WHITE_SPACE;
|
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 91:
|
case 91:
|
||||||
break;
|
break;
|
||||||
case 13: {
|
case 12: {
|
||||||
return handleEolCommentWhitespace(this);
|
yybegin(WAITEOL);
|
||||||
|
return COMMENT;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 92:
|
case 92:
|
||||||
break;
|
break;
|
||||||
case 14: {
|
case 13: {
|
||||||
yybegin(exprOpState);
|
startExpr(ASMOPS, ASMOPS_OP);
|
||||||
return SYMBOL;
|
return WHITE_SPACE;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 93:
|
case 93:
|
||||||
break;
|
break;
|
||||||
case 15: {
|
case 14: {
|
||||||
yybegin(exprOpState);
|
return handleEolCommentWhitespace(this);
|
||||||
return DECIMAL;
|
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 94:
|
case 94:
|
||||||
break;
|
break;
|
||||||
case 16: {
|
case 15: {
|
||||||
return SEPARATOR;
|
yybegin(exprOpState);
|
||||||
|
return SYMBOL;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 95:
|
case 95:
|
||||||
break;
|
break;
|
||||||
case 17: {
|
case 16: {
|
||||||
return HASH;
|
yybegin(exprOpState);
|
||||||
|
return DECIMAL;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 96:
|
case 96:
|
||||||
break;
|
break;
|
||||||
case 18: {
|
case 17: {
|
||||||
return OP_BITWISE_XOR;
|
return SEPARATOR;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 97:
|
case 97:
|
||||||
break;
|
break;
|
||||||
case 19: {
|
case 18: {
|
||||||
return ROUND_L;
|
return HASH;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 98:
|
case 98:
|
||||||
break;
|
break;
|
||||||
case 20: {
|
case 19: {
|
||||||
yybegin(exprOpState);
|
return OP_BITWISE_XOR;
|
||||||
return ROUND_R;
|
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 99:
|
case 99:
|
||||||
break;
|
break;
|
||||||
case 21: {
|
case 20: {
|
||||||
return OP_UNARY_NOT;
|
return ROUND_L;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 100:
|
case 100:
|
||||||
break;
|
break;
|
||||||
case 22: {
|
case 21: {
|
||||||
return OP_UNARY_COMPL;
|
yybegin(exprOpState);
|
||||||
|
return ROUND_R;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 101:
|
case 101:
|
||||||
break;
|
break;
|
||||||
case 23: {
|
case 22: {
|
||||||
return OP_PLUS;
|
return OP_UNARY_NOT;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 102:
|
case 102:
|
||||||
break;
|
break;
|
||||||
case 24: {
|
case 23: {
|
||||||
return OP_MINUS;
|
return OP_UNARY_COMPL;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 103:
|
case 103:
|
||||||
break;
|
break;
|
||||||
case 25: {
|
case 24: {
|
||||||
yybegin(exprOpState);
|
return OP_PLUS;
|
||||||
return CURRENT_PC_SYMBOL;
|
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 104:
|
case 104:
|
||||||
break;
|
break;
|
||||||
case 26: {
|
case 25: {
|
||||||
yybegin(exprState);
|
return OP_MINUS;
|
||||||
return OP_CMP_EQ;
|
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 105:
|
case 105:
|
||||||
break;
|
break;
|
||||||
case 27: {
|
case 26: {
|
||||||
yybegin(exprState);
|
yybegin(exprOpState);
|
||||||
return OP_AR_MOD;
|
return CURRENT_PC_SYMBOL;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 106:
|
case 106:
|
||||||
break;
|
break;
|
||||||
case 28: {
|
case 27: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_CMP_LT;
|
return OP_CMP_EQ;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 107:
|
case 107:
|
||||||
break;
|
break;
|
||||||
case 29: {
|
case 28: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_CMP_GT;
|
return OP_AR_MOD;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 108:
|
case 108:
|
||||||
break;
|
break;
|
||||||
case 30: {
|
case 29: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return SEPARATOR;
|
return OP_CMP_LT;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 109:
|
case 109:
|
||||||
break;
|
break;
|
||||||
case 31: {
|
case 30: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_BITWISE_XOR;
|
return OP_CMP_GT;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 110:
|
case 110:
|
||||||
break;
|
break;
|
||||||
case 32: {
|
case 31: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return ROUND_L;
|
return SEPARATOR;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 111:
|
case 111:
|
||||||
break;
|
break;
|
||||||
case 33: {
|
case 32: {
|
||||||
return ROUND_R;
|
yybegin(exprState);
|
||||||
|
return OP_BITWISE_XOR;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 112:
|
case 112:
|
||||||
break;
|
break;
|
||||||
case 34: {
|
case 33: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_BITWISE_OR;
|
return ROUND_L;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 113:
|
case 113:
|
||||||
break;
|
break;
|
||||||
case 35: {
|
case 34: {
|
||||||
yybegin(exprState);
|
return ROUND_R;
|
||||||
return OP_UNARY_COMPL;
|
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 114:
|
case 114:
|
||||||
break;
|
break;
|
||||||
case 36: {
|
case 35: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_PLUS;
|
return OP_BITWISE_OR;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 115:
|
case 115:
|
||||||
break;
|
break;
|
||||||
case 37: {
|
case 36: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_MINUS;
|
return OP_UNARY_COMPL;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 116:
|
case 116:
|
||||||
break;
|
break;
|
||||||
case 38: {
|
case 37: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_AR_MUL;
|
return OP_PLUS;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 117:
|
case 117:
|
||||||
break;
|
break;
|
||||||
case 39: {
|
case 38: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_BITWISE_AND;
|
return OP_MINUS;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 118:
|
case 118:
|
||||||
break;
|
break;
|
||||||
case 40: {
|
case 39: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_AR_DIV;
|
return OP_AR_MUL;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 119:
|
case 119:
|
||||||
break;
|
break;
|
||||||
case 41: {
|
case 40: {
|
||||||
startExpr(EXPR, EXPR_OP);
|
yybegin(exprState);
|
||||||
return OP_ASSIGN;
|
return OP_BITWISE_AND;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 120:
|
case 120:
|
||||||
break;
|
break;
|
||||||
case 42: {
|
case 41: {
|
||||||
return STRINGLIT;
|
yybegin(exprState);
|
||||||
|
return OP_AR_DIV;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 121:
|
case 121:
|
||||||
break;
|
break;
|
||||||
case 43: {
|
case 42: {
|
||||||
return COMMENT;
|
startExpr(EXPR, EXPR_OP);
|
||||||
|
return OP_ASSIGN;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 122:
|
case 122:
|
||||||
break;
|
break;
|
||||||
|
case 43: {
|
||||||
|
return STRINGLIT;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
case 123:
|
||||||
|
break;
|
||||||
case 44: {
|
case 44: {
|
||||||
|
return COMMENT;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
case 124:
|
||||||
|
break;
|
||||||
|
case 45: {
|
||||||
yybegin(MACROLINE);
|
yybegin(MACROLINE);
|
||||||
macroLines = 0;
|
macroLines = 0;
|
||||||
return WHITE_SPACE;
|
return WHITE_SPACE;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 123:
|
|
||||||
break;
|
|
||||||
case 45: {
|
|
||||||
return MACRO_NAME;
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
case 124:
|
|
||||||
break;
|
|
||||||
case 46: {
|
|
||||||
yybegin(MACROWAITEOL);
|
|
||||||
return COMMENT;
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
case 125:
|
case 125:
|
||||||
break;
|
break;
|
||||||
case 47: {
|
case 46: {
|
||||||
return MACRO_LINE;
|
return MACRO_NAME;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 126:
|
case 126:
|
||||||
break;
|
break;
|
||||||
case 48: {
|
case 47: {
|
||||||
return handleMacroLineEol(this);
|
yybegin(MACROWAITEOL);
|
||||||
|
return COMMENT;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 127:
|
case 127:
|
||||||
break;
|
break;
|
||||||
|
case 48: {
|
||||||
|
return MACRO_LINE;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
case 128:
|
||||||
|
break;
|
||||||
case 49: {
|
case 49: {
|
||||||
|
return handleMacroLineEol(this);
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
case 129:
|
||||||
|
break;
|
||||||
|
case 50: {
|
||||||
yybegin(ASSIGNMENT);
|
yybegin(ASSIGNMENT);
|
||||||
eatOneWhitespace = true;
|
eatOneWhitespace = true;
|
||||||
yypushback(pushbackAssignment(yytext()));
|
yypushback(pushbackAssignment(yytext()));
|
||||||
return SYMBOLDEF;
|
return SYMBOLDEF;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 128:
|
case 130:
|
||||||
break;
|
break;
|
||||||
case 50: {
|
case 51: {
|
||||||
yybegin(INSTRPART);
|
yybegin(INSTRPART);
|
||||||
eatOneWhitespace = false;
|
eatOneWhitespace = false;
|
||||||
yypushback(pushbackLabelColons(yytext()));
|
yypushback(pushbackLabelColons(yytext()));
|
||||||
return LOCAL_LABEL_DEF;
|
return LOCAL_LABEL_DEF;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 129:
|
case 131:
|
||||||
break;
|
break;
|
||||||
case 51: {
|
case 52: {
|
||||||
yybegin(INSTRPART);
|
yybegin(INSTRPART);
|
||||||
yypushback(pushbackLabelColons(yytext()));
|
yypushback(pushbackLabelColons(yytext()));
|
||||||
return GLOBAL_LABEL_DEF;
|
return GLOBAL_LABEL_DEF;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 130:
|
|
||||||
break;
|
|
||||||
case 52: {
|
|
||||||
return OPSIZE_BS;
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
case 131:
|
|
||||||
break;
|
|
||||||
case 53: {
|
|
||||||
return OPSIZE_W;
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
case 132:
|
case 132:
|
||||||
break;
|
break;
|
||||||
case 54: {
|
case 53: {
|
||||||
return OPSIZE_L;
|
return OPSIZE_BS;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 133:
|
case 133:
|
||||||
break;
|
break;
|
||||||
case 55: {
|
case 54: {
|
||||||
yybegin(exprOpState);
|
return OPSIZE_W;
|
||||||
return AREG;
|
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 134:
|
case 134:
|
||||||
break;
|
break;
|
||||||
case 56: {
|
case 55: {
|
||||||
yybegin(exprOpState);
|
return OPSIZE_L;
|
||||||
return REG_SP;
|
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 135:
|
case 135:
|
||||||
break;
|
break;
|
||||||
case 57: {
|
case 56: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return DREG;
|
return AREG;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 136:
|
case 136:
|
||||||
break;
|
break;
|
||||||
case 58: {
|
case 57: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return REG_SR;
|
return REG_SP;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 137:
|
case 137:
|
||||||
break;
|
break;
|
||||||
case 59: {
|
case 58: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return HEXADECIMAL;
|
return DREG;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 138:
|
case 138:
|
||||||
break;
|
break;
|
||||||
case 60: {
|
case 59: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return BINARY;
|
return REG_SR;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 139:
|
case 139:
|
||||||
break;
|
break;
|
||||||
case 61: {
|
case 60: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return OCTAL;
|
return HEXADECIMAL;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 140:
|
case 140:
|
||||||
break;
|
break;
|
||||||
case 62: {
|
case 61: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return STRINGLIT;
|
return BINARY;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 141:
|
case 141:
|
||||||
break;
|
break;
|
||||||
case 63: {
|
case 62: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return PC;
|
return OCTAL;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 142:
|
case 142:
|
||||||
break;
|
break;
|
||||||
case 64: {
|
case 63: {
|
||||||
yybegin(exprState);
|
yybegin(exprOpState);
|
||||||
return OP_CMP_LT_EQ;
|
return STRINGLIT;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 143:
|
case 143:
|
||||||
break;
|
break;
|
||||||
case 65: {
|
case 64: {
|
||||||
yybegin(exprState);
|
yybegin(exprOpState);
|
||||||
return OP_AR_SHIFT_L;
|
return PC;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 144:
|
case 144:
|
||||||
break;
|
break;
|
||||||
case 66: {
|
case 65: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_CMP_NOT_EQ;
|
return OP_CMP_LT_EQ;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 145:
|
case 145:
|
||||||
break;
|
break;
|
||||||
case 67: {
|
case 66: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_CMP_GT_EQ;
|
return OP_AR_SHIFT_L;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 146:
|
case 146:
|
||||||
break;
|
break;
|
||||||
case 68: {
|
case 67: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_AR_SHIFT_R;
|
return OP_CMP_NOT_EQ;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 147:
|
case 147:
|
||||||
break;
|
break;
|
||||||
case 69: {
|
case 68: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_LOGICAL_AND;
|
return OP_CMP_GT_EQ;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 148:
|
case 148:
|
||||||
break;
|
break;
|
||||||
case 70: {
|
case 69: {
|
||||||
yybegin(exprState);
|
yybegin(exprState);
|
||||||
return OP_LOGICAL_OR;
|
return OP_AR_SHIFT_R;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 149:
|
case 149:
|
||||||
break;
|
break;
|
||||||
|
case 70: {
|
||||||
|
yybegin(exprState);
|
||||||
|
return OP_LOGICAL_AND;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
case 150:
|
||||||
|
break;
|
||||||
case 71: {
|
case 71: {
|
||||||
|
yybegin(exprState);
|
||||||
|
return OP_LOGICAL_OR;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
case 151:
|
||||||
|
break;
|
||||||
|
case 72: {
|
||||||
yybegin(INSTRPART);
|
yybegin(INSTRPART);
|
||||||
yypushback(pushbackLabelColons(yytext()));
|
yypushback(pushbackLabelColons(yytext()));
|
||||||
return LOCAL_LABEL_DEF;
|
return LOCAL_LABEL_DEF;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 150:
|
case 152:
|
||||||
break;
|
break;
|
||||||
case 72: {
|
case 73: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return REG_USP;
|
return REG_USP;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 151:
|
case 153:
|
||||||
break;
|
break;
|
||||||
case 73: {
|
case 74: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return REG_CCR;
|
return REG_CCR;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 152:
|
case 154:
|
||||||
break;
|
break;
|
||||||
case 74: {
|
case 75: {
|
||||||
yybegin(exprOpState);
|
yybegin(exprOpState);
|
||||||
return REG_VBR;
|
return REG_VBR;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 153:
|
case 155:
|
||||||
break;
|
break;
|
||||||
case 75: {
|
case 76: {
|
||||||
startExpr(EXPR, EXPR_OP);
|
startExpr(EXPR, EXPR_OP);
|
||||||
return EQU;
|
return EQU;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 154:
|
case 156:
|
||||||
break;
|
break;
|
||||||
case 76: {
|
case 77: {
|
||||||
yybegin(MACRODEF);
|
yybegin(MACRODEF);
|
||||||
return MACRO_TAG;
|
return MACRO_TAG;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 155:
|
case 157:
|
||||||
break;
|
break;
|
||||||
case 77: {
|
case 78: {
|
||||||
return MACRO_TAG;
|
return MACRO_TAG;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 156:
|
case 158:
|
||||||
break;
|
break;
|
||||||
case 78: {
|
case 79: {
|
||||||
yybegin(MACROTERMINATION);
|
yybegin(MACROTERMINATION);
|
||||||
return MACRO_END_TAG;
|
return MACRO_END_TAG;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 157:
|
case 159:
|
||||||
break;
|
break;
|
||||||
case 79: {
|
case 80: {
|
||||||
yybegin(MACRODEF);
|
yybegin(MACRODEF);
|
||||||
yypushback(pushbackAfterFirstToken(yytext()));
|
yypushback(pushbackAfterFirstToken(yytext()));
|
||||||
return MACRO_NAME;
|
return MACRO_NAME;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 158:
|
case 160:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
zzScanError(ZZ_NO_MATCH);
|
zzScanError(ZZ_NO_MATCH);
|
||||||
|
|||||||
@@ -562,9 +562,13 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// Instruction
|
// Instruction|PreprocessorDirective
|
||||||
static boolean InstructionOnly(PsiBuilder b, int l) {
|
static boolean InstructionOnly(PsiBuilder b, int l) {
|
||||||
return Instruction(b, l + 1);
|
if (!recursion_guard_(b, l, "InstructionOnly")) return false;
|
||||||
|
boolean r;
|
||||||
|
r = Instruction(b, l + 1);
|
||||||
|
if (!r) r = PreprocessorDirective(b, l + 1);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
@@ -596,18 +600,27 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// Label Instruction
|
// Label (Instruction|PreprocessorDirective)
|
||||||
static boolean LabelWithInstruction(PsiBuilder b, int l) {
|
static boolean LabelWithInstruction(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "LabelWithInstruction")) return false;
|
if (!recursion_guard_(b, l, "LabelWithInstruction")) return false;
|
||||||
if (!nextTokenIs(b, "", GLOBAL_LABEL_DEF, LOCAL_LABEL_DEF)) return false;
|
if (!nextTokenIs(b, "", GLOBAL_LABEL_DEF, LOCAL_LABEL_DEF)) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b);
|
Marker m = enter_section_(b);
|
||||||
r = Label(b, l + 1);
|
r = Label(b, l + 1);
|
||||||
r = r && Instruction(b, l + 1);
|
r = r && LabelWithInstruction_1(b, l + 1);
|
||||||
exit_section_(b, m, null, r);
|
exit_section_(b, m, null, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instruction|PreprocessorDirective
|
||||||
|
private static boolean LabelWithInstruction_1(PsiBuilder b, int l) {
|
||||||
|
if (!recursion_guard_(b, l, "LabelWithInstruction_1")) return false;
|
||||||
|
boolean r;
|
||||||
|
r = Instruction(b, l + 1);
|
||||||
|
if (!r) r = PreprocessorDirective(b, l + 1);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// LOCAL_LABEL_DEF COLON?
|
// LOCAL_LABEL_DEF COLON?
|
||||||
public static boolean LocalLabel(PsiBuilder b, int l) {
|
public static boolean LocalLabel(PsiBuilder b, int l) {
|
||||||
@@ -817,42 +830,38 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
|
// PreprocessorKeyword PreprocessorOperands?
|
||||||
// PreprocessorOperands?
|
|
||||||
public static boolean PreprocessorDirective(PsiBuilder b, int l) {
|
public static boolean PreprocessorDirective(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "PreprocessorDirective")) return false;
|
if (!recursion_guard_(b, l, "PreprocessorDirective")) return false;
|
||||||
|
if (!nextTokenIs(b, "<preprocessor directive>", DATA_DIRECTIVE, OTHER_DIRECTIVE)) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b, l, _NONE_, PREPROCESSOR_DIRECTIVE, "<preprocessor directive>");
|
Marker m = enter_section_(b, l, _NONE_, PREPROCESSOR_DIRECTIVE, "<preprocessor directive>");
|
||||||
r = PreprocessorDirective_0(b, l + 1);
|
r = PreprocessorKeyword(b, l + 1);
|
||||||
r = r && PreprocessorDirective_1(b, l + 1);
|
r = r && PreprocessorDirective_1(b, l + 1);
|
||||||
r = r && PreprocessorDirective_2(b, l + 1);
|
|
||||||
exit_section_(b, l, m, r, false, null);
|
exit_section_(b, l, m, r, false, null);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Label?
|
// PreprocessorOperands?
|
||||||
private static boolean PreprocessorDirective_0(PsiBuilder b, int l) {
|
|
||||||
if (!recursion_guard_(b, l, "PreprocessorDirective_0")) return false;
|
|
||||||
Label(b, l + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DATA_DIRECTIVE | OTHER_DIRECTIVE
|
|
||||||
private static boolean PreprocessorDirective_1(PsiBuilder b, int l) {
|
private static boolean PreprocessorDirective_1(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "PreprocessorDirective_1")) return false;
|
if (!recursion_guard_(b, l, "PreprocessorDirective_1")) return false;
|
||||||
boolean r;
|
|
||||||
r = consumeToken(b, DATA_DIRECTIVE);
|
|
||||||
if (!r) r = consumeToken(b, OTHER_DIRECTIVE);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreprocessorOperands?
|
|
||||||
private static boolean PreprocessorDirective_2(PsiBuilder b, int l) {
|
|
||||||
if (!recursion_guard_(b, l, "PreprocessorDirective_2")) return false;
|
|
||||||
PreprocessorOperands(b, l + 1);
|
PreprocessorOperands(b, l + 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ********************************************************** */
|
||||||
|
// DATA_DIRECTIVE | OTHER_DIRECTIVE
|
||||||
|
public static boolean PreprocessorKeyword(PsiBuilder b, int l) {
|
||||||
|
if (!recursion_guard_(b, l, "PreprocessorKeyword")) return false;
|
||||||
|
if (!nextTokenIs(b, "<preprocessor keyword>", DATA_DIRECTIVE, OTHER_DIRECTIVE)) return false;
|
||||||
|
boolean r;
|
||||||
|
Marker m = enter_section_(b, l, _NONE_, PREPROCESSOR_KEYWORD, "<preprocessor keyword>");
|
||||||
|
r = consumeToken(b, DATA_DIRECTIVE);
|
||||||
|
if (!r) r = consumeToken(b, OTHER_DIRECTIVE);
|
||||||
|
exit_section_(b, l, m, r, false, null);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// expr
|
// expr
|
||||||
static boolean PreprocessorOperand(PsiBuilder b, int l) {
|
static boolean PreprocessorOperand(PsiBuilder b, int l) {
|
||||||
@@ -1217,14 +1226,12 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// Assignment
|
// Assignment
|
||||||
// | PreprocessorDirective
|
|
||||||
// | LabelInsts
|
// | LabelInsts
|
||||||
public static boolean statement(PsiBuilder b, int l) {
|
public static boolean statement(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "statement")) return false;
|
if (!recursion_guard_(b, l, "statement")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b, l, _NONE_, STATEMENT, "<statement>");
|
Marker m = enter_section_(b, l, _NONE_, STATEMENT, "<statement>");
|
||||||
r = Assignment(b, l + 1);
|
r = Assignment(b, l + 1);
|
||||||
if (!r) r = PreprocessorDirective(b, l + 1);
|
|
||||||
if (!r) r = LabelInsts(b, l + 1);
|
if (!r) r = LabelInsts(b, l + 1);
|
||||||
exit_section_(b, l, m, r, false, M68kParser::statement_recover);
|
exit_section_(b, l, m, r, false, M68kParser::statement_recover);
|
||||||
return r;
|
return r;
|
||||||
@@ -1236,11 +1243,21 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
if (!recursion_guard_(b, l, "statement_recover")) return false;
|
if (!recursion_guard_(b, l, "statement_recover")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b, l, _NOT_);
|
Marker m = enter_section_(b, l, _NOT_);
|
||||||
r = !consumeToken(b, EOL);
|
r = !statement_recover_0(b, l + 1);
|
||||||
exit_section_(b, l, m, r, false, null);
|
exit_section_(b, l, m, r, false, null);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (EOL)
|
||||||
|
private static boolean statement_recover_0(PsiBuilder b, int l) {
|
||||||
|
if (!recursion_guard_(b, l, "statement_recover_0")) return false;
|
||||||
|
boolean r;
|
||||||
|
Marker m = enter_section_(b);
|
||||||
|
r = consumeTokenFast(b, EOL);
|
||||||
|
exit_section_(b, m, null, r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// Expression root: expr
|
// Expression root: expr
|
||||||
// Operator priority table:
|
// Operator priority table:
|
||||||
|
|||||||
@@ -2,17 +2,13 @@
|
|||||||
package de.platon42.intellij.plugins.m68k.psi;
|
package de.platon42.intellij.plugins.m68k.psi;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface M68kPreprocessorDirective extends M68kPsiElement {
|
public interface M68kPreprocessorDirective extends M68kPsiElement {
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
M68kGlobalLabel getGlobalLabel();
|
M68kPreprocessorKeyword getPreprocessorKeyword();
|
||||||
|
|
||||||
@Nullable
|
|
||||||
M68kLocalLabel getLocalLabel();
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
List<M68kExpr> getExprList();
|
List<M68kExpr> getExprList();
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// This is a generated file. Not intended for manual editing.
|
||||||
|
package de.platon42.intellij.plugins.m68k.psi;
|
||||||
|
|
||||||
|
public interface M68kPreprocessorKeyword extends M68kPsiElement {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -58,6 +58,7 @@ public interface M68kTypes {
|
|||||||
IElementType OPERAND_SIZE = new M68kElementType("OPERAND_SIZE");
|
IElementType OPERAND_SIZE = new M68kElementType("OPERAND_SIZE");
|
||||||
IElementType PAREN_EXPR = new M68kElementType("PAREN_EXPR");
|
IElementType PAREN_EXPR = new M68kElementType("PAREN_EXPR");
|
||||||
IElementType PREPROCESSOR_DIRECTIVE = new M68kElementType("PREPROCESSOR_DIRECTIVE");
|
IElementType PREPROCESSOR_DIRECTIVE = new M68kElementType("PREPROCESSOR_DIRECTIVE");
|
||||||
|
IElementType PREPROCESSOR_KEYWORD = new M68kElementType("PREPROCESSOR_KEYWORD");
|
||||||
IElementType PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_NEW_ADDRESSING_MODE = new M68kElementType("PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_NEW_ADDRESSING_MODE");
|
IElementType PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_NEW_ADDRESSING_MODE = new M68kElementType("PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_NEW_ADDRESSING_MODE");
|
||||||
IElementType PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_OLD_ADDRESSING_MODE = new M68kElementType("PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_OLD_ADDRESSING_MODE");
|
IElementType PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_OLD_ADDRESSING_MODE = new M68kElementType("PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_OLD_ADDRESSING_MODE");
|
||||||
IElementType PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE = new M68kElementType("PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE");
|
IElementType PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE = new M68kElementType("PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE");
|
||||||
@@ -233,6 +234,8 @@ public interface M68kTypes {
|
|||||||
return new M68kParenExprImpl(node);
|
return new M68kParenExprImpl(node);
|
||||||
} else if (type == PREPROCESSOR_DIRECTIVE) {
|
} else if (type == PREPROCESSOR_DIRECTIVE) {
|
||||||
return new M68kPreprocessorDirectiveImpl(node);
|
return new M68kPreprocessorDirectiveImpl(node);
|
||||||
|
} else if (type == PREPROCESSOR_KEYWORD) {
|
||||||
|
return new M68kPreprocessorKeywordImpl(node);
|
||||||
} else if (type == PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_NEW_ADDRESSING_MODE) {
|
} else if (type == PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_NEW_ADDRESSING_MODE) {
|
||||||
return new M68kProgramCounterIndirectWithDisplacementNewAddressingModeImpl(node);
|
return new M68kProgramCounterIndirectWithDisplacementNewAddressingModeImpl(node);
|
||||||
} else if (type == PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_OLD_ADDRESSING_MODE) {
|
} else if (type == PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_OLD_ADDRESSING_MODE) {
|
||||||
|
|||||||
@@ -131,6 +131,10 @@ public class M68kVisitor extends PsiElementVisitor {
|
|||||||
visitPsiElement(o);
|
visitPsiElement(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitPreprocessorKeyword(@NotNull M68kPreprocessorKeyword o) {
|
||||||
|
visitPsiElement(o);
|
||||||
|
}
|
||||||
|
|
||||||
public void visitProgramCounterIndirectWithDisplacementNewAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementNewAddressingMode o) {
|
public void visitProgramCounterIndirectWithDisplacementNewAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementNewAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
// visitWithDisplacement(o);
|
// visitWithDisplacement(o);
|
||||||
|
|||||||
+4
-12
@@ -1,17 +1,15 @@
|
|||||||
// This is a generated file. Not intended for manual editing.
|
// This is a generated file. Not intended for manual editing.
|
||||||
package de.platon42.intellij.plugins.m68k.psi.impl;
|
package de.platon42.intellij.plugins.m68k.psi.impl;
|
||||||
|
|
||||||
import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElementVisitor;
|
import com.intellij.psi.PsiElementVisitor;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.*;
|
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class M68kPreprocessorDirectiveImpl extends ASTWrapperPsiElement implements M68kPreprocessorDirective {
|
public class M68kPreprocessorDirectiveImpl extends M68kPreprocessorDirectiveMixin implements M68kPreprocessorDirective {
|
||||||
|
|
||||||
public M68kPreprocessorDirectiveImpl(@NotNull ASTNode node) {
|
public M68kPreprocessorDirectiveImpl(@NotNull ASTNode node) {
|
||||||
super(node);
|
super(node);
|
||||||
@@ -28,15 +26,9 @@ public class M68kPreprocessorDirectiveImpl extends ASTWrapperPsiElement implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@NotNull
|
||||||
public M68kGlobalLabel getGlobalLabel() {
|
public M68kPreprocessorKeyword getPreprocessorKeyword() {
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kGlobalLabel.class);
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kPreprocessorKeyword.class));
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public M68kLocalLabel getLocalLabel() {
|
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kLocalLabel.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
// 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.M68kPreprocessorKeyword;
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class M68kPreprocessorKeywordImpl extends ASTWrapperPsiElement implements M68kPreprocessorKeyword {
|
||||||
|
|
||||||
|
public M68kPreprocessorKeywordImpl(@NotNull ASTNode node) {
|
||||||
|
super(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void accept(@NotNull M68kVisitor visitor) {
|
||||||
|
visitor.visitPreprocessorKeyword(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||||
|
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
|
||||||
|
else super.accept(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ class M68kFileElementType private constructor() : ILightStubFileElementType<PsiF
|
|||||||
@JvmField
|
@JvmField
|
||||||
val INSTANCE = M68kFileElementType()
|
val INSTANCE = M68kFileElementType()
|
||||||
|
|
||||||
const val STUB_VERSION = 5
|
const val STUB_VERSION = 6
|
||||||
const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
|
const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
|
||||||
const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE"
|
const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,15 @@ object AssemblerDirectives {
|
|||||||
"rsset", "clrfo", "clrso", "setfo", "setso"
|
"rsset", "clrfo", "clrso", "setfo", "setso"
|
||||||
)
|
)
|
||||||
|
|
||||||
val otherDirective: Set<String> = setOf(
|
val plainDirectives: Set<String> = setOf(
|
||||||
|
"incdir", "include", "incbin", "output", "idnt",
|
||||||
|
|
||||||
|
"printt", "echo", "fail",
|
||||||
|
|
||||||
|
"opt"
|
||||||
|
)
|
||||||
|
|
||||||
|
val otherDirectives: Set<String> = setOf(
|
||||||
"if",
|
"if",
|
||||||
"ifeq", "ifne", "ifgt", "ifge", "iflt", "ifle", "ifb", "ifnb", "ifc", "ifnc",
|
"ifeq", "ifne", "ifgt", "ifge", "iflt", "ifle", "ifb", "ifnb", "ifc", "ifnc",
|
||||||
"ifd", "ifnd", "ifmacrod", "ifmacrond",
|
"ifd", "ifnd", "ifmacrod", "ifmacrond",
|
||||||
@@ -38,12 +46,10 @@ object AssemblerDirectives {
|
|||||||
"reg", "equr", "equrl",
|
"reg", "equr", "equrl",
|
||||||
"freg", "fequr", "fequrl",
|
"freg", "fequr", "fequrl",
|
||||||
|
|
||||||
"incdir", "include", "incbin", "output",
|
|
||||||
|
|
||||||
"list", "nlist", "nolist", "llen", "nopage", "page", "spc",
|
"list", "nlist", "nolist", "llen", "nopage", "page", "spc",
|
||||||
"org",
|
"org",
|
||||||
|
|
||||||
"assert", "fail", "print", "printt", "printv", "echo",
|
"assert", "printv",
|
||||||
|
|
||||||
"inline", "einline",
|
"inline", "einline",
|
||||||
"rem", "erem",
|
"rem", "erem",
|
||||||
@@ -53,6 +59,6 @@ object AssemblerDirectives {
|
|||||||
|
|
||||||
"basereg", "endb", "far", "near", "initnear",
|
"basereg", "endb", "far", "near", "initnear",
|
||||||
|
|
||||||
"opt"
|
"end"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ enum class AddressMode(val description: String, val syntax: String) {
|
|||||||
PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT("program counter indirect with displacement", "(d16,PC)"),
|
PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT("program counter indirect with displacement", "(d16,PC)"),
|
||||||
ADDRESS_REGISTER_INDIRECT_WITH_INDEX("address register indirect with index", "(d8,An,Xn)"),
|
ADDRESS_REGISTER_INDIRECT_WITH_INDEX("address register indirect with index", "(d8,An,Xn)"),
|
||||||
PROGRAM_COUNTER_INDIRECT_WITH_INDEX("program counter indirect with index", "(d8,PC,Xn)"),
|
PROGRAM_COUNTER_INDIRECT_WITH_INDEX("program counter indirect with index", "(d8,PC,Xn)"),
|
||||||
SPECIAL_REGISTER_DIRECT("special register", "ccr|usp|vbr"),
|
SPECIAL_REGISTER_DIRECT("special register", "sr|ccr|usp|vbr"),
|
||||||
REGISTER_LIST("register list", "list"),
|
REGISTER_LIST("register list", "list"),
|
||||||
IMMEDIATE_DATA("immediate", "#<xxx>"),
|
IMMEDIATE_DATA("immediate", "#<xxx>"),
|
||||||
ABSOLUTE_ADDRESS("absolute short/long", "(xxx).w|l")
|
ABSOLUTE_ADDRESS("absolute short/long", "(xxx).w|l")
|
||||||
@@ -202,6 +202,18 @@ object M68kIsa {
|
|||||||
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val ALL_EXCEPT_AREG_AND_DREG = setOf(
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT,
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
|
||||||
|
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
|
||||||
|
AddressMode.ABSOLUTE_ADDRESS,
|
||||||
|
AddressMode.IMMEDIATE_DATA,
|
||||||
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
|
||||||
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
|
||||||
|
)
|
||||||
|
|
||||||
private val INDIRECT_MODES = setOf(
|
private val INDIRECT_MODES = setOf(
|
||||||
AddressMode.ADDRESS_REGISTER_INDIRECT,
|
AddressMode.ADDRESS_REGISTER_INDIRECT,
|
||||||
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
||||||
@@ -256,33 +268,39 @@ object M68kIsa {
|
|||||||
private val ASD_LSD_MODES = listOf(
|
private val ASD_LSD_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")),
|
||||||
AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("*****")),
|
AllowedAdrMode(INDIRECT_MODES, null, size = OP_SIZE_W, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("*****")),
|
||||||
|
// not an official address mode, but supported by assembler (implicit #1)
|
||||||
|
AllowedAdrMode(DREG_ONLY, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("*****"))
|
||||||
)
|
)
|
||||||
|
|
||||||
private val ROD_MODES = listOf(
|
private val ROD_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")),
|
||||||
AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("-**0*")),
|
AllowedAdrMode(INDIRECT_MODES, null, size = OP_SIZE_W, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("-**0*")),
|
||||||
|
// not an official address mode, but supported by assembler (implicit #1)
|
||||||
|
AllowedAdrMode(DREG_ONLY, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("-**0*")),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val ROXD_MODES = listOf(
|
private val ROXD_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
||||||
AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
AllowedAdrMode(INDIRECT_MODES, null, size = OP_SIZE_W, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
||||||
|
// not an official address mode, but supported by assembler (implicit #1)
|
||||||
|
AllowedAdrMode(DREG_ONLY, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val BCHG_BCLR_BSET_MODES = listOf(
|
private val BCHG_BCLR_BSET_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_L, affectedCc = cc("--*--")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_L, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_B, affectedCc = cc("--*--")),
|
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_B, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_MODIFY_OP2_L, affectedCc = cc("--*--")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_MODIFY_OP2_L, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_MODIFY_OP2_B, affectedCc = cc("--*--")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_AND_DREG, OP_SIZE_B, modInfo = RWM_MODIFY_OP2_B, affectedCc = cc("--*--")),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val BTST_MODES = listOf(
|
private val BTST_MODES = listOf(
|
||||||
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_L, affectedCc = cc("--*--")),
|
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_L, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_B, affectedCc = cc("--*--")),
|
AllowedAdrMode(DREG_ONLY, ALL_EXCEPT_AREG_AND_DREG, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_B, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP2_L, affectedCc = cc("--*--")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP2_L, affectedCc = cc("--*--")),
|
||||||
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP2_B, affectedCc = cc("--*--")),
|
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_AND_DREG, OP_SIZE_B, modInfo = RWM_READ_OP2_B, affectedCc = cc("--*--")),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val conditionCodes =
|
private val conditionCodes =
|
||||||
@@ -354,7 +372,9 @@ object M68kIsa {
|
|||||||
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
|
||||||
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
|
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
|
||||||
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
|
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
|
||||||
AddressMode.ABSOLUTE_ADDRESS
|
AddressMode.ABSOLUTE_ADDRESS,
|
||||||
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
|
||||||
|
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX
|
||||||
),
|
),
|
||||||
setOf(AddressMode.IMMEDIATE_DATA),
|
setOf(AddressMode.IMMEDIATE_DATA),
|
||||||
OP_SIZE_WL,
|
OP_SIZE_WL,
|
||||||
@@ -944,5 +964,5 @@ object M68kIsa {
|
|||||||
private fun isAddressModeMatching(am: AllowedAdrMode, op1: AddressMode?, op2: AddressMode?, specialReg: String?) =
|
private fun isAddressModeMatching(am: AllowedAdrMode, op1: AddressMode?, op2: AddressMode?, specialReg: String?) =
|
||||||
((((op1 == null) && (am.op1 == null)) || am.op1?.contains(op1) ?: false)
|
((((op1 == null) && (am.op1 == null)) || am.op1?.contains(op1) ?: false)
|
||||||
&& (((op2 == null) && (am.op2 == null)) || am.op2?.contains(op2) ?: false)
|
&& (((op2 == null) && (am.op2 == null)) || am.op2?.contains(op2) ?: false)
|
||||||
&& ((specialReg == null) || (specialReg == am.specialReg)))
|
&& ((specialReg == null) || (specialReg.equals(am.specialReg, true))))
|
||||||
}
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.documentation
|
||||||
|
|
||||||
|
import com.intellij.lang.documentation.AbstractDocumentationProvider
|
||||||
|
import com.intellij.lang.documentation.DocumentationMarkup
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import com.intellij.psi.PsiComment
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import com.intellij.util.SmartList
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kStatement
|
||||||
|
|
||||||
|
class M68kGlobalLabelDocumentationProvider : AbstractDocumentationProvider() {
|
||||||
|
|
||||||
|
override fun getQuickNavigateInfo(element: PsiElement, originalElement: PsiElement?): String? {
|
||||||
|
return generateDoc(element, originalElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
|
||||||
|
return if (element is M68kGlobalLabel) {
|
||||||
|
// TODO find out how we can generate inner links for more symbol references inside the expression (DocumentationManagerUtil)
|
||||||
|
val statement = element.parent as M68kStatement
|
||||||
|
var preprocessorDirective = statement.preprocessorDirective
|
||||||
|
if ((preprocessorDirective == null) && (statement.asmInstruction == null) && (statement.macroCall == null)) {
|
||||||
|
val nextLineStatement = PsiTreeUtil.skipWhitespacesAndCommentsForward(PsiTreeUtil.skipWhitespacesAndCommentsForward(statement))
|
||||||
|
as? M68kStatement
|
||||||
|
preprocessorDirective = nextLineStatement?.preprocessorDirective
|
||||||
|
}
|
||||||
|
val content = if (preprocessorDirective != null)
|
||||||
|
DocumentationMarkup.CONTENT_START + StringUtil.escapeXmlEntities(preprocessorDirective.text) + DocumentationMarkup.CONTENT_END
|
||||||
|
else ""
|
||||||
|
val comments = SmartList<String>()
|
||||||
|
var prevToken: PsiElement? = statement
|
||||||
|
do {
|
||||||
|
prevToken = PsiTreeUtil.skipWhitespacesBackward(prevToken)
|
||||||
|
if (prevToken !is PsiComment) break
|
||||||
|
comments.add(prevToken.text)
|
||||||
|
} while (true)
|
||||||
|
val commentpart =
|
||||||
|
if (comments.isNotEmpty()) comments.asReversed().joinToString("<br>", DocumentationMarkup.GRAYED_START, DocumentationMarkup.GRAYED_END) else ""
|
||||||
|
|
||||||
|
commentpart +
|
||||||
|
DocumentationMarkup.DEFINITION_START + StringUtil.escapeXmlEntities(element.name!!) + DocumentationMarkup.DEFINITION_END +
|
||||||
|
content
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-4
@@ -92,8 +92,8 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
val cellsPerRow = ArrayList<HtmlChunk>(3)
|
val cellsPerRow = ArrayList<HtmlChunk>(3)
|
||||||
cellsPerRow.add(contentBuilder.toFragment())
|
cellsPerRow.add(contentBuilder.toFragment())
|
||||||
|
|
||||||
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op1))
|
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op1, allowedAdrMode.specialReg))
|
||||||
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op2))
|
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op2, allowedAdrMode.specialReg))
|
||||||
|
|
||||||
addressModeInfoRows.append(HtmlChunk.tag("tr").children(cellsPerRow.map { it.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL) }))
|
addressModeInfoRows.append(HtmlChunk.tag("tr").children(cellsPerRow.map { it.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL) }))
|
||||||
addressModeInfoRows.toFragment()
|
addressModeInfoRows.toFragment()
|
||||||
@@ -126,11 +126,12 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
return defBuilder
|
return defBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collectAddressModes(addressModes: Set<AddressMode>?): HtmlChunk {
|
private fun collectAddressModes(addressModes: Set<AddressMode>?, specialReg: String?): HtmlChunk {
|
||||||
if (addressModes == null) return HtmlChunk.text("")
|
if (addressModes == null) return HtmlChunk.text("")
|
||||||
val modes = HtmlBuilder()
|
val modes = HtmlBuilder()
|
||||||
addressModes.sortedBy(AddressMode::ordinal)
|
addressModes.sortedBy(AddressMode::ordinal)
|
||||||
.forEach { modes.append(HtmlChunk.text(it.syntax).wrapWith(HtmlChunk.div())) }
|
.map { if (it == AddressMode.SPECIAL_REGISTER_DIRECT) specialReg!! else it.syntax }
|
||||||
|
.forEach { modes.append(HtmlChunk.text(it).wrapWith(HtmlChunk.div())) }
|
||||||
return modes.toFragment()
|
return modes.toFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-13
@@ -79,18 +79,12 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
backtrace.addAll(analyseFlow(register, missingBits, true, initialStatement, linesLimit) {
|
backtrace.addAll(analyseFlow(register, missingBits, true, initialStatement, linesLimit) {
|
||||||
PsiTreeUtil.getPrevSiblingOfType(
|
PsiTreeUtil.getPrevSiblingOfType(it, M68kStatement::class.java)
|
||||||
it,
|
|
||||||
M68kStatement::class.java
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
backtrace.reverse()
|
backtrace.reverse()
|
||||||
val traceBits = (cursorRwm or (cursorRwm ushr RWM_MODIFY_SHIFT) or (cursorRwm ushr RWM_READ_SHIFT)) and RWM_SIZE_MASK
|
val traceBits = (cursorRwm or (cursorRwm ushr RWM_MODIFY_SHIFT) or (cursorRwm ushr RWM_READ_SHIFT)) and RWM_SIZE_MASK
|
||||||
backtrace.addAll(analyseFlow(register, traceBits, false, initialStatement, linesLimit) {
|
backtrace.addAll(analyseFlow(register, traceBits, false, initialStatement, linesLimit) {
|
||||||
PsiTreeUtil.getNextSiblingOfType(
|
PsiTreeUtil.getNextSiblingOfType(it, M68kStatement::class.java)
|
||||||
it,
|
|
||||||
M68kStatement::class.java
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
val statementRows = HtmlBuilder()
|
val statementRows = HtmlBuilder()
|
||||||
@@ -113,7 +107,7 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
var currStatement = startingStatement
|
var currStatement = startingStatement
|
||||||
val statementLines = ArrayList<HtmlChunk>()
|
val statementLines = ArrayList<HtmlChunk>()
|
||||||
val rn = register.regname
|
val rn = register.regname
|
||||||
var addAbrevDots = false
|
var addAbbrevDots = false
|
||||||
var lines = 0
|
var lines = 0
|
||||||
while (missingBits > 0) {
|
while (missingBits > 0) {
|
||||||
val globalLabel = PsiTreeUtil.findChildOfType(currStatement, M68kGlobalLabel::class.java)
|
val globalLabel = PsiTreeUtil.findChildOfType(currStatement, M68kGlobalLabel::class.java)
|
||||||
@@ -127,17 +121,17 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
currStatement = direction.invoke(currStatement) ?: break
|
currStatement = direction.invoke(currStatement) ?: break
|
||||||
val currAsmInstruction = PsiTreeUtil.getChildOfType(currStatement, M68kAsmInstruction::class.java) ?: continue
|
val currAsmInstruction = PsiTreeUtil.getChildOfType(currStatement, M68kAsmInstruction::class.java) ?: continue
|
||||||
if (checkIfInstructionUsesRegister(currAsmInstruction, register)) {
|
if (checkIfInstructionUsesRegister(currAsmInstruction, register)) {
|
||||||
if (addAbrevDots) {
|
if (addAbbrevDots) {
|
||||||
++lines
|
++lines
|
||||||
statementLines.add(createAbbreviationDots())
|
statementLines.add(createAbbreviationDots())
|
||||||
}
|
}
|
||||||
if (++lines > linesLimit) {
|
if (++lines > linesLimit) {
|
||||||
if (!addAbrevDots) {
|
if (!addAbbrevDots) {
|
||||||
statementLines.add(createAbbreviationDots())
|
statementLines.add(createAbbreviationDots())
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
addAbrevDots = false
|
addAbbrevDots = false
|
||||||
val (_, currAdrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(currAsmInstruction) ?: continue
|
val (_, currAdrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(currAsmInstruction) ?: continue
|
||||||
|
|
||||||
val localLabelName = PsiTreeUtil.findChildOfType(currStatement, M68kLocalLabel::class.java)?.name ?: " "
|
val localLabelName = PsiTreeUtil.findChildOfType(currStatement, M68kLocalLabel::class.java)?.name ?: " "
|
||||||
@@ -163,7 +157,7 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
.children(lineBuilder.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL))
|
.children(lineBuilder.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL))
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
addAbrevDots = true
|
addAbbrevDots = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return statementLines
|
return statementLines
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ class M68kSymbolDefinitionDocumentationProvider : AbstractDocumentationProvider(
|
|||||||
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
|
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
|
||||||
return if (element is M68kSymbolDefinition) {
|
return if (element is M68kSymbolDefinition) {
|
||||||
// TODO find out how we can generate inner links for more symbol references inside the expression (DocumentationManagerUtil)
|
// TODO find out how we can generate inner links for more symbol references inside the expression (DocumentationManagerUtil)
|
||||||
val value = (element.getParent() as M68kAssignment).expr.text
|
val value = (element.parent as M68kAssignment).expr.text
|
||||||
DocumentationMarkup.DEFINITION_START + StringUtil.escapeXmlEntities(element.name!!) + DocumentationMarkup.DEFINITION_END +
|
DocumentationMarkup.DEFINITION_START + StringUtil.escapeXmlEntities(element.name!!) + DocumentationMarkup.DEFINITION_END +
|
||||||
DocumentationMarkup.CONTENT_START + StringUtil.escapeXmlEntities(value) + DocumentationMarkup.CONTENT_END
|
DocumentationMarkup.CONTENT_START + StringUtil.escapeXmlEntities(value) + DocumentationMarkup.CONTENT_END
|
||||||
} else null
|
} else null
|
||||||
|
|||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.inspections
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.InspectionSuppressor
|
||||||
|
import com.intellij.codeInspection.ProblemDescriptor
|
||||||
|
import com.intellij.codeInspection.SuppressQuickFix
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiComment
|
||||||
|
import com.intellij.psi.PsiDocumentManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kPsiElement
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kStatement
|
||||||
|
|
||||||
|
class M68kInspectionSuppressor : InspectionSuppressor {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val MARKER = "suppress "
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isSuppressedFor(element: PsiElement, toolId: String): Boolean {
|
||||||
|
if (element !is M68kPsiElement) return false
|
||||||
|
val statement = PsiTreeUtil.getParentOfType(element, M68kStatement::class.java) ?: return false
|
||||||
|
val nextToken = PsiTreeUtil.skipWhitespacesForward(statement)
|
||||||
|
return isSuppressedWithComment(nextToken, toolId) || isSuppressedWithComment(PsiTreeUtil.skipWhitespacesBackward(statement), toolId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSuppressActions(element: PsiElement?, toolId: String): Array<SuppressQuickFix> {
|
||||||
|
return arrayOf(LineSuppressQuickFix(toolId))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isSuppressedWithComment(nextToken: PsiElement?, toolId: String): Boolean {
|
||||||
|
return if (nextToken is PsiComment) {
|
||||||
|
val comment = nextToken.text
|
||||||
|
comment.contains(MARKER) && comment.contains(toolId)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LineSuppressQuickFix(private val toolId: String) : SuppressQuickFix {
|
||||||
|
|
||||||
|
override fun getFamilyName() = "Suppress for statement"
|
||||||
|
|
||||||
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
|
val statement = PsiTreeUtil.getParentOfType(descriptor.startElement, M68kStatement::class.java) ?: return
|
||||||
|
|
||||||
|
val document = PsiDocumentManager.getInstance(project).getDocument(statement.containingFile) ?: return
|
||||||
|
val lineNumber = document.getLineNumber(statement.textOffset)
|
||||||
|
var usePrevLine = false
|
||||||
|
val nextToken = PsiTreeUtil.skipWhitespacesForward(statement)
|
||||||
|
if (nextToken is PsiComment) {
|
||||||
|
val comment = nextToken.text
|
||||||
|
if (comment.contains(MARKER)) {
|
||||||
|
if (!comment.contains(toolId)) {
|
||||||
|
document.insertString(document.getLineEndOffset(lineNumber), " $toolId")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
usePrevLine = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val prevToken = PsiTreeUtil.skipWhitespacesBackward(statement)
|
||||||
|
if (prevToken is PsiComment) {
|
||||||
|
val comment = prevToken.text
|
||||||
|
if (comment.contains(MARKER)) {
|
||||||
|
if (!comment.contains(toolId)) {
|
||||||
|
document.insertString(document.getLineEndOffset(document.getLineNumber(prevToken.textOffset)), " $toolId")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (usePrevLine) {
|
||||||
|
document.insertString(document.getLineStartOffset(lineNumber), "; $MARKER$toolId\n")
|
||||||
|
} else {
|
||||||
|
document.insertString(document.getLineEndOffset(lineNumber), "\t; $MARKER$toolId")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAvailable(project: Project, context: PsiElement) = true
|
||||||
|
|
||||||
|
override fun isSuppressAll() = false
|
||||||
|
}
|
||||||
|
}
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.inspections
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.LocalInspectionToolSession
|
||||||
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
|
import com.intellij.psi.PsiElementVisitor
|
||||||
|
import com.intellij.psi.PsiPolyVariantReference
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor
|
||||||
|
import de.platon42.intellij.plugins.m68k.refs.M68kGlobalLabelSymbolReference
|
||||||
|
|
||||||
|
class M68kUnresolvedReferenceInspection : AbstractBaseM68kLocalInspectionTool() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val DISPLAY_NAME = "Unresolved label/symbol/macro reference"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDisplayName() = DISPLAY_NAME
|
||||||
|
|
||||||
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
|
||||||
|
return object : M68kVisitor() {
|
||||||
|
override fun visitMacroCall(macroCall: M68kMacroCall) {
|
||||||
|
val reference = macroCall.reference as? PsiPolyVariantReference ?: return
|
||||||
|
val resolve = reference.multiResolve(false)
|
||||||
|
if (resolve.isEmpty()) {
|
||||||
|
holder.registerProblem(reference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSymbolReference(symbolReference: M68kSymbolReference) {
|
||||||
|
val references = symbolReference.references ?: return
|
||||||
|
if (references.isEmpty()) return
|
||||||
|
val resolve = references.mapNotNull { it as? PsiPolyVariantReference }
|
||||||
|
.firstNotNullOfOrNull { it.multiResolve(false).ifEmpty { null } }
|
||||||
|
if (resolve == null) {
|
||||||
|
// TODO currently, because macro invocations are not evaluated, mark missing symbols only as weak warning
|
||||||
|
val makeWeak = references.any { it is M68kGlobalLabelSymbolReference }
|
||||||
|
if (makeWeak) {
|
||||||
|
holder.registerProblem(references.first(), ProblemHighlightType.WEAK_WARNING)
|
||||||
|
} else {
|
||||||
|
holder.registerProblem(references.first())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,11 +19,17 @@ object LexerUtil {
|
|||||||
&& text.dropLast(1).endsWith('.')
|
&& text.dropLast(1).endsWith('.')
|
||||||
&& mnemonics.contains(text.dropLast(2).toString().lowercase())
|
&& mnemonics.contains(text.dropLast(2).toString().lowercase())
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isEndDirective(text: CharSequence) = text.contentEquals("end", ignoreCase = true)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isDataDirective(text: CharSequence) = AssemblerDirectives.dataDirectives.contains(text.toString().lowercase())
|
fun isDataDirective(text: CharSequence) = AssemblerDirectives.dataDirectives.contains(text.toString().lowercase())
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isOtherDirective(text: CharSequence) = AssemblerDirectives.otherDirective.contains(text.toString().lowercase())
|
fun isPlainDirective(text: CharSequence) = AssemblerDirectives.plainDirectives.contains(text.toString().lowercase())
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isOtherDirective(text: CharSequence) = AssemblerDirectives.otherDirectives.contains(text.toString().lowercase())
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun pushbackAssignment(text: CharSequence): Int {
|
fun pushbackAssignment(text: CharSequence): Int {
|
||||||
@@ -52,7 +58,7 @@ object LexerUtil {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun handleMacroMode(lexer: _M68kLexer): IElementType {
|
fun handleMacroMode(lexer: _M68kLexer): IElementType {
|
||||||
if (lexer.lexerPrefs.macroParametersUnparsed) {
|
if (lexer.lexerPrefs.macroParametersUnparsed) {
|
||||||
lexer.yybegin(_M68kLexer.MACROCALL)
|
lexer.yybegin(_M68kLexer.PLAINPARAMS)
|
||||||
} else {
|
} else {
|
||||||
lexer.yybegin(_M68kLexer.ASMOPS)
|
lexer.yybegin(_M68kLexer.ASMOPS)
|
||||||
}
|
}
|
||||||
@@ -69,4 +75,13 @@ object LexerUtil {
|
|||||||
lexer.yybegin(_M68kLexer.MACROLINE)
|
lexer.yybegin(_M68kLexer.MACROLINE)
|
||||||
return TokenType.WHITE_SPACE
|
return TokenType.WHITE_SPACE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun unquoteString(string: String) = string.run {
|
||||||
|
when {
|
||||||
|
startsWith('"') -> removeSurrounding("\"")
|
||||||
|
startsWith('\'') -> removeSurrounding("'")
|
||||||
|
startsWith('<') -> removeSurrounding("<", ">")
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ HASH_COMMENT=([#;*].*+)
|
|||||||
SKIP_TO_EOL=[^\r\n]+
|
SKIP_TO_EOL=[^\r\n]+
|
||||||
PLAIN_MACRO_LINE=[^;\r\n]+
|
PLAIN_MACRO_LINE=[^;\r\n]+
|
||||||
|
|
||||||
%state NOSOL,INSTRPART,ASMINSTR,ASMOPS,ASMOPS_OP,ASSIGNMENT,EXPR,EXPR_OP,MACROCALL,WAITEOL,MACRODEF,MACROLINE,MACROTERMINATION,MACROWAITEOL
|
%state NOSOL,INSTRPART,ASMINSTR,ASMOPS,ASMOPS_OP,ASSIGNMENT,EXPR,EXPR_OP,PLAINPARAMS,WAITEOL,MACRODEF,MACROLINE,MACROTERMINATION,MACROWAITEOL
|
||||||
|
|
||||||
%%
|
%%
|
||||||
<YYINITIAL, NOSOL>
|
<YYINITIAL, NOSOL>
|
||||||
@@ -81,7 +81,7 @@ PLAIN_MACRO_LINE=[^;\r\n]+
|
|||||||
{HASH_COMMENT} { yybegin(YYINITIAL); return COMMENT; }
|
{HASH_COMMENT} { yybegin(YYINITIAL); return COMMENT; }
|
||||||
}
|
}
|
||||||
|
|
||||||
<INSTRPART,ASMINSTR,MACROCALL,ASSIGNMENT,EXPR,EXPR_OP,ASMOPS,ASMOPS_OP>
|
<INSTRPART,ASMINSTR,PLAINPARAMS,ASSIGNMENT,EXPR,EXPR_OP,ASMOPS,ASMOPS_OP>
|
||||||
{
|
{
|
||||||
{EOL} { yybegin(YYINITIAL); return EOL; }
|
{EOL} { yybegin(YYINITIAL); return EOL; }
|
||||||
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
|
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
|
||||||
@@ -92,7 +92,7 @@ PLAIN_MACRO_LINE=[^;\r\n]+
|
|||||||
{WHITE_SPACE} { return WHITE_SPACE; }
|
{WHITE_SPACE} { return WHITE_SPACE; }
|
||||||
}
|
}
|
||||||
|
|
||||||
<MACROCALL, EXPR, EXPR_OP, ASMOPS, ASMOPS_OP> {
|
<PLAINPARAMS, EXPR, EXPR_OP, ASMOPS, ASMOPS_OP> {
|
||||||
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
|
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +102,7 @@ PLAIN_MACRO_LINE=[^;\r\n]+
|
|||||||
{MACRO_DEF_LEFT} { yybegin(MACRODEF); yypushback(pushbackAfterFirstToken(yytext())); return MACRO_NAME; }
|
{MACRO_DEF_LEFT} { yybegin(MACRODEF); yypushback(pushbackAfterFirstToken(yytext())); return MACRO_NAME; }
|
||||||
{LOCAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
|
{LOCAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
|
||||||
{GLOBAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
|
{GLOBAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
|
||||||
|
"." { yybegin(INSTRPART); eatOneWhitespace = false; return LOCAL_LABEL_DEF; }
|
||||||
}
|
}
|
||||||
|
|
||||||
<NOSOL> {
|
<NOSOL> {
|
||||||
@@ -116,7 +117,9 @@ PLAIN_MACRO_LINE=[^;\r\n]+
|
|||||||
{DIRECTIVE_KEYWORD} {
|
{DIRECTIVE_KEYWORD} {
|
||||||
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
|
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
|
||||||
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
|
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
|
||||||
|
//if(isEndDirective(yytext())) { yybegin(YYINITIAL); zzAtEOF = true; return null; }
|
||||||
if(isDataDirective(yytext())) { startExpr(EXPR, EXPR_OP); return DATA_DIRECTIVE; }
|
if(isDataDirective(yytext())) { startExpr(EXPR, EXPR_OP); return DATA_DIRECTIVE; }
|
||||||
|
if(isPlainDirective(yytext())) { yybegin(PLAINPARAMS); return OTHER_DIRECTIVE; }
|
||||||
if(isOtherDirective(yytext())) { startExpr(EXPR, EXPR_OP); return OTHER_DIRECTIVE; }
|
if(isOtherDirective(yytext())) { startExpr(EXPR, EXPR_OP); return OTHER_DIRECTIVE; }
|
||||||
return handleMacroMode(this);
|
return handleMacroMode(this);
|
||||||
}
|
}
|
||||||
@@ -136,7 +139,7 @@ PLAIN_MACRO_LINE=[^;\r\n]+
|
|||||||
{OPSIZE_L} { return OPSIZE_L; }
|
{OPSIZE_L} { return OPSIZE_L; }
|
||||||
}
|
}
|
||||||
|
|
||||||
<MACROCALL> {
|
<PLAINPARAMS> {
|
||||||
"," { return SEPARATOR; }
|
"," { return SEPARATOR; }
|
||||||
|
|
||||||
{PLAINPARAM} { return STRINGLIT; }
|
{PLAINPARAM} { return STRINGLIT; }
|
||||||
|
|||||||
@@ -121,11 +121,10 @@ M68kFile ::= line*
|
|||||||
private line ::= !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
|
private line ::= !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
|
||||||
|
|
||||||
statement ::= (Assignment
|
statement ::= (Assignment
|
||||||
| PreprocessorDirective
|
|
||||||
| LabelInsts)
|
| LabelInsts)
|
||||||
{pin=1 recoverWhile=statement_recover};
|
{pin = 1 recoverWhile = statement_recover}
|
||||||
|
|
||||||
private statement_recover ::= !(EOL)
|
private statement_recover ::= !(EOL) { consumeTokenMethod = "consumeTokenFast" }
|
||||||
|
|
||||||
SymbolDefinition ::= SYMBOLDEF {
|
SymbolDefinition ::= SYMBOLDEF {
|
||||||
implements = "de.platon42.intellij.plugins.m68k.psi.M68kNamedElement"
|
implements = "de.platon42.intellij.plugins.m68k.psi.M68kNamedElement"
|
||||||
@@ -140,8 +139,8 @@ Assignment ::= SymbolDefinition COLON? (OP_ASSIGN|EQU) expr
|
|||||||
private LabelInsts ::= LabelWithInstruction | LabelOnly | InstructionOnly
|
private LabelInsts ::= LabelWithInstruction | LabelOnly | InstructionOnly
|
||||||
|
|
||||||
private LabelOnly ::= Label
|
private LabelOnly ::= Label
|
||||||
private LabelWithInstruction ::= Label Instruction
|
private LabelWithInstruction ::= Label (Instruction|PreprocessorDirective)
|
||||||
private InstructionOnly ::= Instruction
|
private InstructionOnly ::= (Instruction|PreprocessorDirective)
|
||||||
|
|
||||||
LocalLabel ::= LOCAL_LABEL_DEF COLON? {
|
LocalLabel ::= LOCAL_LABEL_DEF COLON? {
|
||||||
name = "local label"
|
name = "local label"
|
||||||
@@ -173,8 +172,11 @@ AsmOp ::= MNEMONIC OperandSize? {
|
|||||||
methods = [getMnemonic getOpSize]
|
methods = [getMnemonic getOpSize]
|
||||||
}
|
}
|
||||||
|
|
||||||
PreprocessorDirective ::= Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
|
PreprocessorKeyword ::= (DATA_DIRECTIVE | OTHER_DIRECTIVE)
|
||||||
PreprocessorOperands?
|
|
||||||
|
PreprocessorDirective ::= PreprocessorKeyword PreprocessorOperands? {
|
||||||
|
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kPreprocessorDirectiveMixin"
|
||||||
|
}
|
||||||
|
|
||||||
MacroPlainLine ::= MACRO_LINE
|
MacroPlainLine ::= MACRO_LINE
|
||||||
MacroNameDefinition ::= MACRO_NAME
|
MacroNameDefinition ::= MACRO_NAME
|
||||||
|
|||||||
@@ -62,11 +62,4 @@ object M68kAddressModeUtil {
|
|||||||
else -> throw IllegalArgumentException("Unknown addressing mode $addressingMode")
|
else -> throw IllegalArgumentException("Unknown addressing mode $addressingMode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mergeReadWriteModifyRegisters(regset: Set<Pair<Register, Int>>): Set<Pair<Register, Int>> {
|
|
||||||
if (regset.size <= 1) return regset
|
|
||||||
return regset.groupBy({ it.first }) { it.second }
|
|
||||||
.map { it.key to if (it.value.size == 1) it.value.single() else it.value.reduce(Int::or) }
|
|
||||||
.toSet()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,11 @@ object M68kElementFactory {
|
|||||||
return PsiTreeUtil.findChildOfType(file, M68kMacroCall::class.java)!!
|
return PsiTreeUtil.findChildOfType(file, M68kMacroCall::class.java)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createIncludeStatement(project: Project, path: String): M68kPreprocessorDirective {
|
||||||
|
val file = createFile(project, " include \"$path\"\n")
|
||||||
|
return PsiTreeUtil.findChildOfType(file, M68kPreprocessorDirective::class.java)!!
|
||||||
|
}
|
||||||
|
|
||||||
fun createFile(project: Project, content: String): M68kFile {
|
fun createFile(project: Project, content: String): M68kFile {
|
||||||
return PsiFileFactory.getInstance(project).createFileFromText("dummy.m68k", INSTANCE, content) as M68kFile
|
return PsiFileFactory.getInstance(project).createFileFromText("dummy.m68k", INSTANCE, content) as M68kFile
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,13 @@ package de.platon42.intellij.plugins.m68k.psi
|
|||||||
|
|
||||||
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||||
import com.intellij.lang.ASTNode
|
import com.intellij.lang.ASTNode
|
||||||
|
import de.platon42.intellij.plugins.m68k.lexer.LexerUtil
|
||||||
|
|
||||||
abstract class M68kLiteralExprMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kLiteralExpr {
|
abstract class M68kLiteralExprMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kLiteralExpr {
|
||||||
override fun getValue(): Any? {
|
override fun getValue(): Any? {
|
||||||
val childNode = firstChild.node
|
val childNode = firstChild.node
|
||||||
when (childNode.elementType) {
|
when (childNode.elementType) {
|
||||||
M68kTypes.STRINGLIT -> {
|
M68kTypes.STRINGLIT -> LexerUtil.unquoteString(childNode.text)
|
||||||
return text.run {
|
|
||||||
when {
|
|
||||||
startsWith('"') -> removeSurrounding("\"")
|
|
||||||
startsWith('\'') -> removeSurrounding("'")
|
|
||||||
startsWith('<') -> removeSurrounding(">")
|
|
||||||
else -> this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
M68kTypes.DECIMAL -> {
|
M68kTypes.DECIMAL -> {
|
||||||
try {
|
try {
|
||||||
return childNode.text.toInt()
|
return childNode.text.toInt()
|
||||||
@@ -46,6 +38,6 @@ abstract class M68kLiteralExprMixin(node: ASTNode) : ASTWrapperPsiElement(node),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return text
|
return childNode.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,10 @@ import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
|
|||||||
|
|
||||||
abstract class M68kMacroCallMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kMacroCall {
|
abstract class M68kMacroCallMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kMacroCall {
|
||||||
|
|
||||||
|
override fun getReference(): PsiReference? {
|
||||||
|
return references.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
override fun getReferences(): Array<PsiReference> {
|
override fun getReferences(): Array<PsiReference> {
|
||||||
return ReferenceProvidersRegistry.getReferencesFromProviders(this)
|
return ReferenceProvidersRegistry.getReferencesFromProviders(this)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
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 M68kPreprocessorDirectiveMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kPreprocessorDirective {
|
||||||
|
|
||||||
|
override fun getReference(): PsiReference? {
|
||||||
|
return references.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getReferences(): Array<PsiReference> {
|
||||||
|
return ReferenceProvidersRegistry.getReferencesFromProviders(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ object M68kPsiImplUtil {
|
|||||||
|
|
||||||
// Local Label
|
// Local Label
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getName(element: M68kLocalLabel): String? = element.firstChild.text
|
fun getName(element: M68kLocalLabel): String? = element.firstChild?.text
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setName(element: M68kLocalLabel, name: String): PsiElement {
|
fun setName(element: M68kLocalLabel, name: String): PsiElement {
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
|
|||||||
|
|
||||||
abstract class M68kSymbolReferenceMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kSymbolReference {
|
abstract class M68kSymbolReferenceMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kSymbolReference {
|
||||||
|
|
||||||
|
override fun getReference(): PsiReference? {
|
||||||
|
return references.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
override fun getReferences(): Array<PsiReference> {
|
override fun getReferences(): Array<PsiReference> {
|
||||||
return ReferenceProvidersRegistry.getReferencesFromProviders(this)
|
return ReferenceProvidersRegistry.getReferencesFromProviders(this)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.refs
|
||||||
|
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import com.intellij.psi.impl.source.resolve.ResolveCache
|
||||||
|
import com.intellij.psi.search.FileTypeIndex
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import de.platon42.intellij.plugins.m68k.M68kFileType
|
||||||
|
import de.platon42.intellij.plugins.m68k.lexer.LexerUtil
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kPreprocessorDirective
|
||||||
|
|
||||||
|
class M68kIncludeFileReference(element: M68kPreprocessorDirective) : PsiPolyVariantReferenceBase<M68kPreprocessorDirective>(element, true) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val INSTANCE = Resolver()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Resolver : ResolveCache.PolyVariantResolver<M68kIncludeFileReference> {
|
||||||
|
override fun resolve(ref: M68kIncludeFileReference, incompleteCode: Boolean): Array<ResolveResult> {
|
||||||
|
val project = ref.element.project
|
||||||
|
val allFiles = FileTypeIndex.getFiles(M68kFileType.INSTANCE, GlobalSearchScope.allScope(project))
|
||||||
|
|
||||||
|
val pathName = LexerUtil.unquoteString(ref.element.exprList.first().text).replace('\\', '/')
|
||||||
|
val fileMatched = ((allFiles.firstOrNull { it.path.equals(pathName, ignoreCase = true) }
|
||||||
|
?: allFiles.firstOrNull { it.path.endsWith(pathName.removePrefix("../"), ignoreCase = true) })
|
||||||
|
?: allFiles.firstOrNull { it.path.endsWith(pathName.substringAfterLast('/'), ignoreCase = true) }) ?: return emptyArray()
|
||||||
|
return PsiElementResolveResult.createResults(PsiManager.getInstance(project).findFile(fileMatched))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
// override fun getRangeInElement(): TextRange {
|
||||||
|
// val unquoted = LexerUtil.unquoteString(element.text)
|
||||||
|
//
|
||||||
|
// val path = element.exprList.first()
|
||||||
|
// return TextRange.from(
|
||||||
|
// path.textRange.startOffset + path.text.indexOf(unquoted), unquoted.length
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
}
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
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.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import com.intellij.util.ProcessingContext
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.*
|
||||||
|
|
||||||
|
class M68kLocalLabelDefCompletionContributor : CompletionContributor() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
extend(
|
||||||
|
CompletionType.BASIC,
|
||||||
|
PlatformPatterns.or(PlatformPatterns.psiElement(M68kTypes.LOCAL_LABEL_DEF), PlatformPatterns.psiElement(M68kTypes.GLOBAL_LABEL_DEF)),
|
||||||
|
object : CompletionProvider<CompletionParameters>() {
|
||||||
|
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
|
||||||
|
var topLevelElement = parameters.originalFile.findElementAt(parameters.offset)
|
||||||
|
while (topLevelElement?.parent !is M68kFile) {
|
||||||
|
topLevelElement = topLevelElement?.parent ?: return
|
||||||
|
}
|
||||||
|
// TODO find out if we can cache this somehow
|
||||||
|
val affectedStatements = ArrayList<M68kStatement>()
|
||||||
|
val definedLocalLabels = HashSet<String>()
|
||||||
|
val referencedLocalLabels = HashSet<String>()
|
||||||
|
findUndefinedLocalLabels(topLevelElement, affectedStatements, definedLocalLabels, referencedLocalLabels) {
|
||||||
|
PsiTreeUtil.getNextSiblingOfType(it, M68kStatement::class.java)
|
||||||
|
}
|
||||||
|
findUndefinedLocalLabels(topLevelElement, affectedStatements, definedLocalLabels, referencedLocalLabels) {
|
||||||
|
PsiTreeUtil.getPrevSiblingOfType(it, M68kStatement::class.java)
|
||||||
|
}
|
||||||
|
referencedLocalLabels.removeAll(definedLocalLabels)
|
||||||
|
resultSet.addAllElements(
|
||||||
|
if (parameters.originalPosition?.text == ".") {
|
||||||
|
referencedLocalLabels.map { LookupElementBuilder.create(it.removePrefix(".")) }
|
||||||
|
} else {
|
||||||
|
referencedLocalLabels.map(LookupElementBuilder::create)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findUndefinedLocalLabels(
|
||||||
|
topLevelElement: PsiElement,
|
||||||
|
affectedStatements: MutableList<M68kStatement>,
|
||||||
|
definedLocalLabels: MutableSet<String>,
|
||||||
|
referencedLocalLabels: MutableSet<String>,
|
||||||
|
direction: (topLevelElement: PsiElement) -> M68kStatement?
|
||||||
|
) {
|
||||||
|
var currStatement = topLevelElement
|
||||||
|
while (true) {
|
||||||
|
currStatement = direction.invoke(currStatement) ?: break
|
||||||
|
val globalLabel = PsiTreeUtil.findChildOfType(currStatement, M68kGlobalLabel::class.java)
|
||||||
|
if (globalLabel != null) break
|
||||||
|
affectedStatements.add(currStatement)
|
||||||
|
val localLabel = PsiTreeUtil.findChildOfType(currStatement, M68kLocalLabel::class.java)
|
||||||
|
if (localLabel != null) definedLocalLabels.add(localLabel.name!!)
|
||||||
|
val symbolReferences = PsiTreeUtil.findChildrenOfAnyType(currStatement, M68kSymbolReference::class.java)
|
||||||
|
if (symbolReferences.isNotEmpty()) {
|
||||||
|
referencedLocalLabels.addAll(
|
||||||
|
symbolReferences.filter(M68kSymbolReference::isLocalLabelRef).map(M68kSymbolReference::getSymbolName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.platon42.intellij.plugins.m68k.refs
|
package de.platon42.intellij.plugins.m68k.refs
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
@@ -14,11 +15,15 @@ import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
|
|||||||
import de.platon42.intellij.plugins.m68k.psi.M68kStatement
|
import de.platon42.intellij.plugins.m68k.psi.M68kStatement
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
|
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
|
||||||
|
|
||||||
class M68kLocalLabelReference(element: M68kSymbolReference) : PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
|
class M68kLocalLabelReference(element: M68kSymbolReference) :
|
||||||
|
PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)),
|
||||||
|
EmptyResolveMessageProvider {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val INSTANCE = Resolver()
|
val INSTANCE = Resolver()
|
||||||
|
|
||||||
|
private const val UNRESOLVED_MESSAGE_PATTERN = "Cannot resolve local label ''{0}''"
|
||||||
|
|
||||||
fun findLocalLabels(element: M68kSymbolReference, predicate: (M68kLocalLabel) -> Boolean): List<M68kLocalLabel> {
|
fun findLocalLabels(element: M68kSymbolReference, predicate: (M68kLocalLabel) -> Boolean): List<M68kLocalLabel> {
|
||||||
val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!!
|
val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!!
|
||||||
val results = SmartList<M68kLocalLabel>()
|
val results = SmartList<M68kLocalLabel>()
|
||||||
@@ -42,6 +47,8 @@ class M68kLocalLabelReference(element: M68kSymbolReference) : PsiPolyVariantRefe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getUnresolvedMessagePattern() = UNRESOLVED_MESSAGE_PATTERN
|
||||||
|
|
||||||
class Resolver : ResolveCache.PolyVariantResolver<M68kLocalLabelReference> {
|
class Resolver : ResolveCache.PolyVariantResolver<M68kLocalLabelReference> {
|
||||||
override fun resolve(ref: M68kLocalLabelReference, incompleteCode: Boolean): Array<ResolveResult> {
|
override fun resolve(ref: M68kLocalLabelReference, incompleteCode: Boolean): Array<ResolveResult> {
|
||||||
val refName = ref.element.symbolName
|
val refName = ref.element.symbolName
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.platon42.intellij.plugins.m68k.refs
|
package de.platon42.intellij.plugins.m68k.refs
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiElementResolveResult
|
import com.intellij.psi.PsiElementResolveResult
|
||||||
@@ -14,12 +15,16 @@ import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
|
|||||||
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex
|
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex
|
||||||
|
|
||||||
class M68kMacroReference(element: M68kMacroCall) :
|
class M68kMacroReference(element: M68kMacroCall) :
|
||||||
PsiPolyVariantReferenceBase<M68kMacroCall>(element, TextRange(0, element.macroName.length)) {
|
PsiPolyVariantReferenceBase<M68kMacroCall>(element, TextRange(0, element.macroName.length)), EmptyResolveMessageProvider {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val INSTANCE = Resolver()
|
val INSTANCE = Resolver()
|
||||||
|
|
||||||
|
private const val UNRESOLVED_MESSAGE_PATTERN = "Cannot resolve macro ''{0}''"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getUnresolvedMessagePattern() = UNRESOLVED_MESSAGE_PATTERN
|
||||||
|
|
||||||
class Resolver : ResolveCache.PolyVariantResolver<M68kMacroReference> {
|
class Resolver : ResolveCache.PolyVariantResolver<M68kMacroReference> {
|
||||||
override fun resolve(ref: M68kMacroReference, incompleteCode: Boolean): Array<ResolveResult> {
|
override fun resolve(ref: M68kMacroReference, incompleteCode: Boolean): Array<ResolveResult> {
|
||||||
val macroName = ref.element.macroName
|
val macroName = ref.element.macroName
|
||||||
|
|||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.refs
|
||||||
|
|
||||||
|
import com.intellij.history.core.Paths
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.AbstractElementManipulator
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import com.intellij.util.IncorrectOperationException
|
||||||
|
import de.platon42.intellij.plugins.m68k.lexer.LexerUtil
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kLiteralExpr
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kPreprocessorDirective
|
||||||
|
|
||||||
|
class M68kPreprocessorDirectiveElementManipulator : AbstractElementManipulator<M68kPreprocessorDirective>() {
|
||||||
|
|
||||||
|
@Throws(IncorrectOperationException::class)
|
||||||
|
override fun handleContentChange(element: M68kPreprocessorDirective, range: TextRange, newContent: String): M68kPreprocessorDirective {
|
||||||
|
val oldPath = LexerUtil.unquoteString(element.exprList.first().text)
|
||||||
|
.replace('\\', '/')
|
||||||
|
.substringBeforeLast('/', missingDelimiterValue = "")
|
||||||
|
val newIncludeStatement = M68kElementFactory.createIncludeStatement(element.project, Paths.appended(oldPath, newContent))
|
||||||
|
PsiTreeUtil.findChildOfType(element, M68kLiteralExpr::class.java)!!.replace(newIncludeStatement.exprList.first())
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getRangeInElement(element: M68kPreprocessorDirective): TextRange {
|
||||||
|
val pathExpr = element.exprList.first()
|
||||||
|
val unquotedPath = LexerUtil.unquoteString(pathExpr.text)
|
||||||
|
return if (unquotedPath.length < pathExpr.textLength) {
|
||||||
|
TextRange.from(pathExpr.startOffsetInParent + 1, unquotedPath.length)
|
||||||
|
} else {
|
||||||
|
pathExpr.textRangeInParent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,9 @@ package de.platon42.intellij.plugins.m68k.refs
|
|||||||
import com.intellij.patterns.PlatformPatterns
|
import com.intellij.patterns.PlatformPatterns
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kLiteralExpr
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
|
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kPreprocessorDirective
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
|
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
|
||||||
|
|
||||||
class M68kReferenceContributor : PsiReferenceContributor() {
|
class M68kReferenceContributor : PsiReferenceContributor() {
|
||||||
@@ -12,12 +14,14 @@ class M68kReferenceContributor : PsiReferenceContributor() {
|
|||||||
val localLabelReferenceProvider = LocalLabelReferenceProvider()
|
val localLabelReferenceProvider = LocalLabelReferenceProvider()
|
||||||
val globalLabelReferenceProvider = GlobalLabelSymbolReferenceProvider()
|
val globalLabelReferenceProvider = GlobalLabelSymbolReferenceProvider()
|
||||||
val macroReferenceProvider = MacroReferenceProvider()
|
val macroReferenceProvider = MacroReferenceProvider()
|
||||||
|
val includeFileReferenceProvider = IncludeFileReferenceProvider()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
|
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
|
||||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), localLabelReferenceProvider)
|
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), localLabelReferenceProvider)
|
||||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), globalLabelReferenceProvider)
|
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), globalLabelReferenceProvider)
|
||||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kMacroCall::class.java), macroReferenceProvider)
|
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kMacroCall::class.java), macroReferenceProvider)
|
||||||
|
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kPreprocessorDirective::class.java), includeFileReferenceProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalLabelReferenceProvider : PsiReferenceProvider() {
|
class LocalLabelReferenceProvider : PsiReferenceProvider() {
|
||||||
@@ -40,4 +44,16 @@ class M68kReferenceContributor : PsiReferenceContributor() {
|
|||||||
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> =
|
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> =
|
||||||
arrayOf(M68kMacroReference(element as M68kMacroCall))
|
arrayOf(M68kMacroReference(element as M68kMacroCall))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IncludeFileReferenceProvider : PsiReferenceProvider() {
|
||||||
|
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
|
||||||
|
val directive = element as M68kPreprocessorDirective
|
||||||
|
if (directive.exprList.firstOrNull() !is M68kLiteralExpr) return emptyArray()
|
||||||
|
return if (directive.preprocessorKeyword.text.equals("include", ignoreCase = true)) {
|
||||||
|
arrayOf(M68kIncludeFileReference(directive))
|
||||||
|
} else {
|
||||||
|
emptyArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.platon42.intellij.plugins.m68k.scanner
|
package de.platon42.intellij.plugins.m68k.scanner
|
||||||
|
|
||||||
|
import com.intellij.lang.HelpID
|
||||||
import com.intellij.lang.cacheBuilder.DefaultWordsScanner
|
import com.intellij.lang.cacheBuilder.DefaultWordsScanner
|
||||||
import com.intellij.lang.cacheBuilder.WordsScanner
|
import com.intellij.lang.cacheBuilder.WordsScanner
|
||||||
import com.intellij.lang.findUsages.FindUsagesProvider
|
import com.intellij.lang.findUsages.FindUsagesProvider
|
||||||
@@ -22,14 +23,19 @@ class M68kFindUsagesProvider : FindUsagesProvider {
|
|||||||
TokenSet.EMPTY
|
TokenSet.EMPTY
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun canFindUsagesFor(psiElement: PsiElement): Boolean = psiElement is M68kNamedElement
|
override fun canFindUsagesFor(psiElement: PsiElement): Boolean =
|
||||||
|
when (psiElement) {
|
||||||
|
is M68kNamedElement, is M68kSymbolReference, is M68kMacroCall, is M68kFile, is M68kRegister -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
override fun getHelpId(psiElement: PsiElement): @NonNls String? = null
|
override fun getHelpId(psiElement: PsiElement): @NonNls String = HelpID.FIND_OTHER_USAGES
|
||||||
|
|
||||||
override fun getType(element: PsiElement): @Nls String {
|
override fun getType(element: PsiElement): @Nls String {
|
||||||
return when (element) {
|
return when (element) {
|
||||||
is M68kGlobalLabel -> "global label"
|
is M68kGlobalLabel -> "global label"
|
||||||
is M68kLocalLabel -> "local label"
|
is M68kLocalLabel -> "local label"
|
||||||
|
is M68kPreprocessorDirective -> "preprocessor directive"
|
||||||
is M68kSymbolDefinition -> "symbol definition"
|
is M68kSymbolDefinition -> "symbol definition"
|
||||||
is M68kSymbolReference -> "symbol reference"
|
is M68kSymbolReference -> "symbol reference"
|
||||||
is M68kMacroDefinition -> "macro definition"
|
is M68kMacroDefinition -> "macro definition"
|
||||||
@@ -44,6 +50,7 @@ class M68kFindUsagesProvider : FindUsagesProvider {
|
|||||||
return when (element) {
|
return when (element) {
|
||||||
is M68kGlobalLabel -> element.name!!
|
is M68kGlobalLabel -> element.name!!
|
||||||
is M68kLocalLabel -> element.name!!
|
is M68kLocalLabel -> element.name!!
|
||||||
|
is M68kPreprocessorDirective -> element.text
|
||||||
is M68kSymbolDefinition -> element.parent.text
|
is M68kSymbolDefinition -> element.parent.text
|
||||||
is M68kSymbolReference -> element.symbolName
|
is M68kSymbolReference -> element.symbolName
|
||||||
is M68kMacroDefinition -> element.macroNameDefinition.text
|
is M68kMacroDefinition -> element.macroNameDefinition.text
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.scanner
|
||||||
|
|
||||||
|
import com.intellij.openapi.fileTypes.FileType
|
||||||
|
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.psi.impl.include.FileIncludeInfo
|
||||||
|
import com.intellij.psi.impl.include.FileIncludeProvider
|
||||||
|
import com.intellij.psi.impl.source.tree.LightTreeUtil
|
||||||
|
import com.intellij.util.Consumer
|
||||||
|
import com.intellij.util.PathUtilRt
|
||||||
|
import com.intellij.util.indexing.FileContent
|
||||||
|
import com.intellij.util.indexing.PsiDependentFileContent
|
||||||
|
import de.platon42.intellij.plugins.m68k.M68kFileType.Companion.INSTANCE
|
||||||
|
import de.platon42.intellij.plugins.m68k.lexer.LexerUtil
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
|
||||||
|
|
||||||
|
class M68kIncludeFileProvider : FileIncludeProvider() {
|
||||||
|
|
||||||
|
override fun getId(): String {
|
||||||
|
return "mc68000_include"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun acceptFile(file: VirtualFile): Boolean {
|
||||||
|
return FileTypeRegistry.getInstance().isFileOfType(file, INSTANCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerFileTypesUsedForIndexing(fileTypeSink: Consumer<in FileType?>) {
|
||||||
|
fileTypeSink.consume(INSTANCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIncludeInfos(content: FileContent): Array<FileIncludeInfo> {
|
||||||
|
if (content.contentAsText.indexOfAny(listOf("include", "incbin"), ignoreCase = true) < 0) return emptyArray()
|
||||||
|
|
||||||
|
val tree = (content as PsiDependentFileContent).lighterAST
|
||||||
|
val statements = LightTreeUtil.getChildrenOfType(tree, tree.root, M68kTypes.STATEMENT).asSequence()
|
||||||
|
.mapNotNull { LightTreeUtil.firstChildOfType(tree, it, M68kTypes.PREPROCESSOR_DIRECTIVE) }
|
||||||
|
.mapNotNull {
|
||||||
|
val keywordNode = LightTreeUtil.firstChildOfType(tree, it, M68kTypes.PREPROCESSOR_KEYWORD) ?: return@mapNotNull null
|
||||||
|
val keyword = LightTreeUtil.toFilteredString(tree, keywordNode, null)
|
||||||
|
if (keyword.equals("include", true) || keyword.equals("incbin", true)) {
|
||||||
|
keyword to it
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mapNotNull {
|
||||||
|
val pathNode = LightTreeUtil.firstChildOfType(tree, it.second, M68kTypes.LITERAL_EXPR) ?: return@mapNotNull null
|
||||||
|
val path = LexerUtil.unquoteString(LightTreeUtil.toFilteredString(tree, pathNode, null)).replace('\\', '/')
|
||||||
|
if (it.first.equals("include", true)) {
|
||||||
|
FileIncludeInfo(path)
|
||||||
|
} else {
|
||||||
|
FileIncludeInfo(PathUtilRt.getFileName(path), path, 0, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.toList()
|
||||||
|
|
||||||
|
return statements.toTypedArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<fileType name="MC68000 Assembler" implementationClass="de.platon42.intellij.plugins.m68k.M68kFileType"
|
<fileType name="MC68000 Assembler" implementationClass="de.platon42.intellij.plugins.m68k.M68kFileType"
|
||||||
fieldName="INSTANCE" language="MC68000" extensions="asm;ASM;s;S;i"/>
|
fieldName="INSTANCE" language="MC68000" extensions="asm;s;i"/>
|
||||||
<lang.parserDefinition language="MC68000"
|
<lang.parserDefinition language="MC68000"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.parser.M68kParserDefinition"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.parser.M68kParserDefinition"/>
|
||||||
<lang.syntaxHighlighterFactory language="MC68000"
|
<lang.syntaxHighlighterFactory language="MC68000"
|
||||||
@@ -24,17 +24,23 @@
|
|||||||
<colorSettingsPage implementation="de.platon42.intellij.plugins.m68k.syntax.M68kColorSettingsPage"/>
|
<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.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.M68kGlobalLabelSymbolCompletionContributor"/>
|
||||||
|
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kLocalLabelDefCompletionContributor"/>
|
||||||
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallCompletionContributor"/>
|
<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.braceMatcher language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.syntax.M68kPairedBraceMatcher"/>
|
||||||
<lang.quoteHandler language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.M68kStringQuoteHandler"/>
|
<lang.quoteHandler language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.M68kStringQuoteHandler"/>
|
||||||
<lang.findUsagesProvider language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.scanner.M68kFindUsagesProvider"/>
|
<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.psiStructureViewFactory language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.structureview.M68kStructureViewFactory"/>
|
||||||
|
<lang.inspectionSuppressor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kInspectionSuppressor"/>
|
||||||
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference"
|
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kSymbolReferenceElementManipulator"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kSymbolReferenceElementManipulator"/>
|
||||||
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kMacroCall"
|
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kMacroCall"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallElementManipulator"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallElementManipulator"/>
|
||||||
|
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kPreprocessorDirective"
|
||||||
|
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kPreprocessorDirectiveElementManipulator"/>
|
||||||
<lang.documentationProvider language="MC68000"
|
<lang.documentationProvider language="MC68000"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kSymbolDefinitionDocumentationProvider"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kSymbolDefinitionDocumentationProvider"/>
|
||||||
|
<lang.documentationProvider language="MC68000"
|
||||||
|
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kGlobalLabelDocumentationProvider"/>
|
||||||
<lang.documentationProvider language="MC68000"
|
<lang.documentationProvider language="MC68000"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kRegisterFlowDocumentationProvider"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kRegisterFlowDocumentationProvider"/>
|
||||||
<lang.documentationProvider language="MC68000"
|
<lang.documentationProvider language="MC68000"
|
||||||
@@ -43,9 +49,10 @@
|
|||||||
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex"/>
|
<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.M68kSymbolDefinitionStubIndex"/>
|
||||||
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex"/>
|
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex"/>
|
||||||
<psi.referenceContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
|
<psi.referenceContributor language="MC68000" implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
|
||||||
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
|
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
|
||||||
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>
|
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>
|
||||||
|
<include.provider implementation="de.platon42.intellij.plugins.m68k.scanner.M68kIncludeFileProvider"/>
|
||||||
|
|
||||||
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kSyntaxInspection"
|
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kSyntaxInspection"
|
||||||
displayName="Assembly instruction validity" groupName="M68k"
|
displayName="Assembly instruction validity" groupName="M68k"
|
||||||
@@ -56,6 +63,9 @@
|
|||||||
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kUnexpectedConditionalInstructionInspection"
|
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kUnexpectedConditionalInstructionInspection"
|
||||||
displayName="Unaffected condition codes before conditional instruction" groupName="M68k"
|
displayName="Unaffected condition codes before conditional instruction" groupName="M68k"
|
||||||
enabledByDefault="true" level="WARNING"/>
|
enabledByDefault="true" level="WARNING"/>
|
||||||
|
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kUnresolvedReferenceInspection"
|
||||||
|
displayName="Unresolved label/symbol/macro reference" groupName="M68k"
|
||||||
|
enabledByDefault="true" level="WARNING"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<actions>
|
<actions>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
Checks if references to symbols, macros, global and local labels are resolvable.
|
||||||
|
<!-- tooltip end -->
|
||||||
|
<p>Currently, issues a weak warning for global labels or symbols as those
|
||||||
|
can be defined via macros, which are not evaluated right now</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.documentation
|
||||||
|
|
||||||
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
|
import de.platon42.intellij.jupiter.LightCodeInsightExtension
|
||||||
|
import de.platon42.intellij.jupiter.MyFixture
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
|
||||||
|
@ExtendWith(LightCodeInsightExtension::class)
|
||||||
|
internal class M68kGlobalLabelDocumentationProviderTest : AbstractDocumentationProviderTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun check_documentation_for_a_label_definition(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.configureByText(
|
||||||
|
"documentme.asm", """
|
||||||
|
rts
|
||||||
|
; inputs: d0 = number
|
||||||
|
|
||||||
|
; output: d0 = square
|
||||||
|
squareme: include "fancysquarecode.asm"
|
||||||
|
rts
|
||||||
|
bsr square<caret>me
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
assertThat(generateDocumentation(myFixture))
|
||||||
|
.isEqualTo("<span class='grayed'>; inputs: d0 = number<br>; output: d0 = square</span><div class='definition'><pre>squareme</pre></div><div class='content'>include "fancysquarecode.asm"</div>")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun check_documentation_for_a_label_definition_next_line(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.configureByText(
|
||||||
|
"documentme.asm", """
|
||||||
|
; output: d0 = square
|
||||||
|
square<caret>me:
|
||||||
|
; oh man
|
||||||
|
include "fancysquarecode.asm"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
assertThat(generateDocumentation(myFixture))
|
||||||
|
.isEqualTo("<span class='grayed'>; output: d0 = square</span><div class='definition'><pre>squareme</pre></div><div class='content'>include "fancysquarecode.asm"</div>")
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -108,6 +108,16 @@ internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationP
|
|||||||
assertThat(generateDocumentation(myFixture)).contains("Reset External Devices", "(privileged)")
|
assertThat(generateDocumentation(myFixture)).contains("Reset External Devices", "(privileged)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun check_documentation_for_instruction_with_special_register(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.configureByText(
|
||||||
|
"documentme.asm", """
|
||||||
|
<caret>move.l usp,a0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
assertThat(generateDocumentation(myFixture)).contains("<div>usp</div>")
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
internal fun check_documentation_if_there_is_no_concrete_match(@MyFixture myFixture: CodeInsightTestFixture) {
|
internal fun check_documentation_if_there_is_no_concrete_match(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
myFixture.configureByText(
|
myFixture.configureByText(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.platon42.intellij.plugins.m68k.inspections
|
package de.platon42.intellij.plugins.m68k.inspections
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
import de.platon42.intellij.jupiter.LightCodeInsightExtension
|
import de.platon42.intellij.jupiter.LightCodeInsightExtension
|
||||||
import de.platon42.intellij.jupiter.TestDataPath
|
import de.platon42.intellij.jupiter.TestDataPath
|
||||||
@@ -16,4 +17,16 @@ abstract class AbstractInspectionTest : AbstractM68kTest() {
|
|||||||
assertThat(myFixture.doHighlighting())
|
assertThat(myFixture.doHighlighting())
|
||||||
.areExactly(count, Condition({ it.description?.contains(snippet) ?: false }, "containing"))
|
.areExactly(count, Condition({ it.description?.contains(snippet) ?: false }, "containing"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun executeQuickFixes(myFixture: CodeInsightTestFixture, regex: Regex, expectedFixes: Int) {
|
||||||
|
val quickfixes = getQuickFixes(myFixture, regex, expectedFixes)
|
||||||
|
assertThat(quickfixes.groupBy { it.familyName }).hasSize(1)
|
||||||
|
quickfixes.forEach(myFixture::launchAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun getQuickFixes(myFixture: CodeInsightTestFixture, regex: Regex, expectedFixes: Int): List<IntentionAction> {
|
||||||
|
val quickfixes = myFixture.getAllQuickFixes().filter { it.text.matches(regex) }
|
||||||
|
assertThat(quickfixes).`as`("Fixes matched by $regex: ${myFixture.getAllQuickFixes().map { it.text }}").hasSize(expectedFixes)
|
||||||
|
return quickfixes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.inspections
|
||||||
|
|
||||||
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
|
import de.platon42.intellij.jupiter.MyFixture
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
internal class M68kInspectionSuppressorTest : AbstractInspectionTest() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val SUPPRESS_FOR_STATEMENT = "Suppress for statement"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun suppresses_inspection_with_end_of_line_comment(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kSyntaxInspection::class.java)
|
||||||
|
myFixture.configureByText("syntax.asm", " rts d0 ; suppress M68kSyntax")
|
||||||
|
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun suppresses_inspection_with_full_line_comment_on_line_before(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kSyntaxInspection::class.java)
|
||||||
|
myFixture.configureByText("syntax.asm", "; suppress M68kSyntax\n rts d0")
|
||||||
|
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun suppression_works_without_prior_comment(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kSyntaxInspection::class.java)
|
||||||
|
myFixture.configureByText("syntax.asm", " rts<caret> d0")
|
||||||
|
executeSuppressAction(myFixture, SUPPRESS_FOR_STATEMENT)
|
||||||
|
myFixture.checkResult(" rts d0\t; suppress M68kSyntax")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun suppression_works_with_prior_suppression_comment(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kSyntaxInspection::class.java)
|
||||||
|
myFixture.configureByText("syntax.asm", " rts<caret> d0; suppress foobar")
|
||||||
|
executeSuppressAction(myFixture, SUPPRESS_FOR_STATEMENT)
|
||||||
|
myFixture.checkResult(" rts d0; suppress foobar M68kSyntax")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun suppression_works_with_prior_suppression_comment_in_line_above(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kSyntaxInspection::class.java)
|
||||||
|
myFixture.configureByText("syntax.asm", "; suppress foobar\n rts<caret> d0")
|
||||||
|
executeSuppressAction(myFixture, SUPPRESS_FOR_STATEMENT)
|
||||||
|
myFixture.checkResult("; suppress foobar M68kSyntax\n rts d0")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun suppression_works_by_adding_suppression_comment_in_line_above(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kSyntaxInspection::class.java)
|
||||||
|
myFixture.configureByText("syntax.asm", " rts<caret> d0 ; unrelated comment")
|
||||||
|
executeSuppressAction(myFixture, SUPPRESS_FOR_STATEMENT)
|
||||||
|
myFixture.checkResult("; suppress M68kSyntax\n rts d0 ; unrelated comment")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun executeSuppressAction(myFixture: CodeInsightTestFixture, suppressAction: String) {
|
||||||
|
val highlightInfos = myFixture.doHighlighting()
|
||||||
|
assertThat(highlightInfos).hasSize(1)
|
||||||
|
val quickFixPair = highlightInfos[0].quickFixActionRanges[0]
|
||||||
|
val intentionActionDescriptor = quickFixPair.first
|
||||||
|
val element = myFixture.file.findElementAt(quickFixPair.second.startOffset)!!
|
||||||
|
val suppressQuickFix = intentionActionDescriptor.getOptions(element, myFixture.editor)!!
|
||||||
|
.first { it.text == suppressAction }
|
||||||
|
myFixture.launchAction(suppressQuickFix)
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -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 M68kUnresolvedReferenceInspectionTest : AbstractInspectionTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun shows_warning_on_undefined_symbol_label(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kUnresolvedReferenceInspection::class.java)
|
||||||
|
myFixture.configureByText("unresolvedref.asm", " bra foobar")
|
||||||
|
assertHighlightings(myFixture, 1, "Cannot resolve symbol 'foobar'")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun shows_warning_on_undefined_local_label(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kUnresolvedReferenceInspection::class.java)
|
||||||
|
myFixture.configureByText("unresolvedref.asm", " bra .foobar")
|
||||||
|
assertHighlightings(myFixture, 1, "Cannot resolve local label '.foobar'")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun shows_warning_on_undefined_macro(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kUnresolvedReferenceInspection::class.java)
|
||||||
|
myFixture.configureByText("unresolvedref.asm", " foobar")
|
||||||
|
assertHighlightings(myFixture, 1, "Cannot resolve macro 'foobar'")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -87,6 +87,11 @@ internal class AddressingModesTest : AbstractParsingTest() {
|
|||||||
testGoodSyntax(testCase, " move.l 4.w,a6\n")
|
testGoodSyntax(testCase, " move.l 4.w,a6\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun btst_quirk(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
|
testGoodSyntax(testCase, " btst #5,#42\n btst d0,#42")
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
internal fun movem_register_list(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
internal fun movem_register_list(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
testGoodSyntax(testCase, " movem.l d0-d2/d4/a0/a2-a3/a5,-(sp)\n")
|
testGoodSyntax(testCase, " movem.l d0-d2/d4/a0/a2-a3/a5,-(sp)\n")
|
||||||
@@ -118,7 +123,7 @@ internal class AddressingModesTest : AbstractParsingTest() {
|
|||||||
internal fun special_register_move(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
internal fun special_register_move(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
testGoodSyntax(
|
testGoodSyntax(
|
||||||
testCase, " move.l usp,a0\n"
|
testCase, " move.l usp,a0\n"
|
||||||
+ " move.l a5,usp\n"
|
+ " move.l a5,USP\n"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.parser
|
||||||
|
|
||||||
|
import de.platon42.intellij.jupiter.MyTestCase
|
||||||
|
import de.platon42.intellij.jupiter.ParsingTestExtension
|
||||||
|
import de.platon42.intellij.jupiter.TestDataSubPath
|
||||||
|
import org.junit.jupiter.api.Disabled
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
@TestDataSubPath("directives")
|
||||||
|
internal class EndDirectiveTest : AbstractParsingTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled("END directive detection breaks stuff, need to find a different solution")
|
||||||
|
internal fun end_directive(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
|
testGoodSyntax(
|
||||||
|
testCase, """
|
||||||
|
moveq.l #0,d0
|
||||||
|
rts
|
||||||
|
END narf
|
||||||
|
äöö#öä235r2352ou485742q3535p3ü
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,4 +22,14 @@ internal class OtherDirectivesTest : AbstractParsingTest() {
|
|||||||
internal fun if_defined_block(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
internal fun if_defined_block(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
testGoodSyntax(testCase, "\tIFD DEBUG ; cause a crash\n illegal\n ENDC\n")
|
testGoodSyntax(testCase, "\tIFD DEBUG ; cause a crash\n illegal\n ENDC\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun kalms_include_file_special_quote(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
|
testGoodSyntax(testCase, " include\t<Engine/A500/System/Copper.i>")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun opt_directive(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
|
testGoodSyntax(testCase, " opt o+,w-")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
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 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 M68kLocalLabelDefCompletionContributorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun completion_shows_undefined_local_labels_without_dot_prefix(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.configureByText(
|
||||||
|
"completeme.asm", """
|
||||||
|
main
|
||||||
|
.loop
|
||||||
|
dbra d0,.loop
|
||||||
|
dbra d1,.loop2
|
||||||
|
.<caret>
|
||||||
|
bra.s .foo
|
||||||
|
rts
|
||||||
|
|
||||||
|
coolsubroutine
|
||||||
|
bra.s .narf
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
myFixture.completeBasic()
|
||||||
|
assertThat(myFixture.lookupElementStrings).containsExactlyInAnyOrder("loop2", "foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun completion_shows_undefined_local_labels_even_without_dot(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.configureByText(
|
||||||
|
"completeme.asm", """
|
||||||
|
main
|
||||||
|
.loop
|
||||||
|
dbra d0,.loop
|
||||||
|
dbra d1,.loop2
|
||||||
|
<caret>
|
||||||
|
bra.s .foo
|
||||||
|
bra.s bar$
|
||||||
|
rts
|
||||||
|
|
||||||
|
coolsubroutine
|
||||||
|
bra.s .narf
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
myFixture.completeBasic()
|
||||||
|
assertThat(myFixture.lookupElementStrings).containsExactlyInAnyOrder(".loop2", ".foo", "bar$")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package de.platon42.intellij.plugins.m68k.refs
|
|||||||
|
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.search.FilenameIndex
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
import de.platon42.intellij.jupiter.LightCodeInsightExtension
|
import de.platon42.intellij.jupiter.LightCodeInsightExtension
|
||||||
import de.platon42.intellij.jupiter.MyFixture
|
import de.platon42.intellij.jupiter.MyFixture
|
||||||
@@ -86,4 +88,44 @@ internal class M68kReferenceContributorTest : AbstractM68kTest() {
|
|||||||
|
|
||||||
myFixture.checkResultByFile("macros_after_rename.asm")
|
myFixture.checkResultByFile("macros_after_rename.asm")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun reference_to_file_can_be_renamed(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.addFileToProject("otherfile.asm", "; oh no!")
|
||||||
|
val file = myFixture.configureByText(
|
||||||
|
"fileref.asm", """
|
||||||
|
include "otherfil<caret>e.asm"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
val reference = file.findReferenceAt(myFixture.editor.caretModel.offset)
|
||||||
|
assertThat(reference).isInstanceOf(M68kIncludeFileReference::class.java)
|
||||||
|
val otherfile = reference!!.resolve() as M68kFile
|
||||||
|
assertThat(otherfile.text).isEqualTo("; oh no!")
|
||||||
|
|
||||||
|
myFixture.renameElementAtCaret("foobar.asm")
|
||||||
|
val files = FilenameIndex.getFilesByName(myFixture.project, "foobar.asm", GlobalSearchScope.allScope(myFixture.project))
|
||||||
|
assertThat(files).hasSize(1)
|
||||||
|
|
||||||
|
assertThat(file.text).isEqualToIgnoringWhitespace("include \"foobar.asm\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun reference_to_file_in_a_subdirectory_can_be_renamed(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.addFileToProject("foobar/otherfile.asm", "; oh no!")
|
||||||
|
val file = myFixture.configureByText(
|
||||||
|
"fileref.asm", """
|
||||||
|
include "foobar/otherfil<caret>e.asm"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
val reference = file.findReferenceAt(myFixture.editor.caretModel.offset)
|
||||||
|
assertThat(reference).isInstanceOf(M68kIncludeFileReference::class.java)
|
||||||
|
val otherfile = reference!!.resolve() as M68kFile
|
||||||
|
assertThat(otherfile.text).isEqualTo("; oh no!")
|
||||||
|
|
||||||
|
myFixture.renameElementAtCaret("foobar.asm")
|
||||||
|
val files = FilenameIndex.getFilesByName(myFixture.project, "foobar.asm", GlobalSearchScope.allScope(myFixture.project))
|
||||||
|
assertThat(files).hasSize(1)
|
||||||
|
|
||||||
|
assertThat(file.text).isEqualToIgnoringWhitespace("include \"foobar/foobar.asm\"")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.scanner
|
||||||
|
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.psi.impl.include.FileIncludeManager
|
||||||
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
|
import de.platon42.intellij.jupiter.LightCodeInsightExtension
|
||||||
|
import de.platon42.intellij.jupiter.MyFixture
|
||||||
|
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
|
||||||
|
|
||||||
|
@ExtendWith(LightCodeInsightExtension::class)
|
||||||
|
internal class M68kIncludeFileProviderTest : AbstractM68kTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun accepts_a_couple_of_include_statements(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.addFileToProject("macros.i", "PUSHM MACRO\n ENDM")
|
||||||
|
myFixture.addFileToProject("exec/execbase.i", "; Commodore include")
|
||||||
|
myFixture.addFileToProject("exec/exec.i", " include execbase.i")
|
||||||
|
myFixture.addFileToProject("includes/hardware/custom.i", "; Another Commodore include")
|
||||||
|
myFixture.addFileToProject("data/ease_x.bin", "binary file")
|
||||||
|
myFixture.addFileToProject("fx/fx_angle_only.S", "; Nosfe!!")
|
||||||
|
myFixture.configureByText(
|
||||||
|
"completeme.asm", """
|
||||||
|
include macros.i
|
||||||
|
include "exec/exec.i"
|
||||||
|
include <../src/includes/hardware/custom.i>
|
||||||
|
incbin "data/ease_x.bin"
|
||||||
|
include fx\fx_angle_only.S
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
val includedFiles = FileIncludeManager.getManager(myFixture.project).getIncludedFiles(myFixture.file.virtualFile, true, true)
|
||||||
|
assertThat(includedFiles).extracting<String>(VirtualFile::getName)
|
||||||
|
.containsExactlyInAnyOrder("completeme.asm", "macros.i", "fx_angle_only.S", "custom.i", "exec.i", "execbase.i")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
Assembly File: a.asm
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kAsmInstructionImpl(ASM_INSTRUCTION)
|
||||||
|
M68kAsmOpImpl(ASM_OP)
|
||||||
|
PsiElement(M68kTokenType.MNEMONIC)('btst')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kImmediateDataImpl(IMMEDIATE_DATA)
|
||||||
|
PsiElement(M68kTokenType.HASH)('#')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.DECIMAL)('5')
|
||||||
|
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||||
|
M68kImmediateDataImpl(IMMEDIATE_DATA)
|
||||||
|
PsiElement(M68kTokenType.HASH)('#')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.DECIMAL)('42')
|
||||||
|
PsiElement(M68kTokenType.EOL)('\n')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kAsmInstructionImpl(ASM_INSTRUCTION)
|
||||||
|
M68kAsmOpImpl(ASM_OP)
|
||||||
|
PsiElement(M68kTokenType.MNEMONIC)('btst')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
|
||||||
|
M68kDataRegisterImpl(DATA_REGISTER)
|
||||||
|
PsiElement(M68kTokenType.DREG)('d0')
|
||||||
|
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||||
|
M68kImmediateDataImpl(IMMEDIATE_DATA)
|
||||||
|
PsiElement(M68kTokenType.HASH)('#')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.DECIMAL)('42')
|
||||||
@@ -29,5 +29,5 @@ Assembly File: a.asm
|
|||||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||||
M68kSpecialRegisterDirectAddressingModeImpl(SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE)
|
M68kSpecialRegisterDirectAddressingModeImpl(SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE)
|
||||||
M68kSpecialRegisterImpl(SPECIAL_REGISTER)
|
M68kSpecialRegisterImpl(SPECIAL_REGISTER)
|
||||||
PsiElement(M68kTokenType.REG_USP)('usp')
|
PsiElement(M68kTokenType.REG_USP)('USP')
|
||||||
PsiElement(M68kTokenType.EOL)('\n')
|
PsiElement(M68kTokenType.EOL)('\n')
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
Assembly File: a.asm
|
Assembly File: a.asm
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kGlobalLabelImpl(GLOBAL_LABEL)
|
||||||
|
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('foo')
|
||||||
|
PsiElement(M68kTokenType.COLON)(':')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
M68kGlobalLabelImpl(GLOBAL_LABEL)
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('foo')
|
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.b')
|
||||||
PsiElement(M68kTokenType.COLON)(':')
|
|
||||||
PsiWhiteSpace(' ')
|
|
||||||
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.b')
|
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kLiteralExprImpl(LITERAL_EXPR)
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
PsiElement(M68kTokenType.STRINGLIT)(''It could be good!'')
|
PsiElement(M68kTokenType.STRINGLIT)(''It could be good!'')
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ Assembly File: a.asm
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.w')
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
|
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.w')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kLiteralExprImpl(LITERAL_EXPR)
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
PsiElement(M68kTokenType.DECIMAL)('0')
|
PsiElement(M68kTokenType.DECIMAL)('0')
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
Assembly File: a.asm
|
||||||
|
PsiWhiteSpace('\n')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kAsmInstructionImpl(ASM_INSTRUCTION)
|
||||||
|
M68kAsmOpImpl(ASM_OP)
|
||||||
|
PsiElement(M68kTokenType.MNEMONIC)('moveq')
|
||||||
|
M68kOperandSizeImpl(OPERAND_SIZE)
|
||||||
|
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kImmediateDataImpl(IMMEDIATE_DATA)
|
||||||
|
PsiElement(M68kTokenType.HASH)('#')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.DECIMAL)('0')
|
||||||
|
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||||
|
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
|
||||||
|
M68kDataRegisterImpl(DATA_REGISTER)
|
||||||
|
PsiElement(M68kTokenType.DREG)('d0')
|
||||||
|
PsiElement(M68kTokenType.EOL)('\n')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kAsmInstructionImpl(ASM_INSTRUCTION)
|
||||||
|
M68kAsmOpImpl(ASM_OP)
|
||||||
|
PsiElement(M68kTokenType.MNEMONIC)('rts')
|
||||||
|
PsiElement(M68kTokenType.EOL)('\n')
|
||||||
|
PsiWhiteSpace(' END narf\n äöö#öä235r2352ou485742q3535p3ü\n')
|
||||||
@@ -2,7 +2,8 @@ Assembly File: a.asm
|
|||||||
PsiWhiteSpace('\t')
|
PsiWhiteSpace('\t')
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
PsiElement(M68kTokenType.DATA_DIRECTIVE)('even')
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
|
PsiElement(M68kTokenType.DATA_DIRECTIVE)('even')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiComment(M68kTokenType.COMMENT)('; align to even address')
|
PsiComment(M68kTokenType.COMMENT)('; align to even address')
|
||||||
PsiElement(M68kTokenType.EOL)('\n')
|
PsiElement(M68kTokenType.EOL)('\n')
|
||||||
@@ -2,7 +2,8 @@ Assembly File: a.asm
|
|||||||
PsiWhiteSpace('\t')
|
PsiWhiteSpace('\t')
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('IFD')
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
|
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('IFD')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kRefExprImpl(REF_EXPR)
|
M68kRefExprImpl(REF_EXPR)
|
||||||
M68kSymbolReferenceImpl(SYMBOL_REFERENCE)
|
M68kSymbolReferenceImpl(SYMBOL_REFERENCE)
|
||||||
@@ -19,5 +20,6 @@ Assembly File: a.asm
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('ENDC')
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
|
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('ENDC')
|
||||||
PsiElement(M68kTokenType.EOL)('\n')
|
PsiElement(M68kTokenType.EOL)('\n')
|
||||||
@@ -2,7 +2,8 @@ Assembly File: a.asm
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('include')
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
|
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('include')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kLiteralExprImpl(LITERAL_EXPR)
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
PsiElement(M68kTokenType.STRINGLIT)('"exec/execbase.i"')
|
PsiElement(M68kTokenType.STRINGLIT)('"exec/execbase.i"')
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
Assembly File: a.asm
|
Assembly File: a.asm
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kGlobalLabelImpl(GLOBAL_LABEL)
|
||||||
|
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('howto')
|
||||||
|
PsiElement(M68kTokenType.COLON)(':')
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
M68kGlobalLabelImpl(GLOBAL_LABEL)
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('howto')
|
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('incbin')
|
||||||
PsiElement(M68kTokenType.COLON)(':')
|
|
||||||
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('incbin')
|
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kRefExprImpl(REF_EXPR)
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
M68kSymbolReferenceImpl(SYMBOL_REFERENCE)
|
PsiElement(M68kTokenType.STRINGLIT)('Convertedassets\scroller_howto.raw.BPL')
|
||||||
PsiElement(M68kTokenType.SYMBOL)('Convertedassets\scroller_howto.raw.BPL')
|
|
||||||
PsiElement(M68kTokenType.EOL)('\n')
|
PsiElement(M68kTokenType.EOL)('\n')
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
Assembly File: a.asm
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
|
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('include')
|
||||||
|
PsiWhiteSpace('\t')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.STRINGLIT)('<Engine/A500/System/Copper.i>')
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
Assembly File: a.asm
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kStatementImpl(STATEMENT)
|
||||||
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
|
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('opt')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.STRINGLIT)('o+')
|
||||||
|
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||||
|
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||||
|
PsiElement(M68kTokenType.STRINGLIT)('w-')
|
||||||
@@ -2,7 +2,8 @@ Assembly File: a.asm
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.w')
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
|
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.w')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kBinarySubExprImpl(BINARY_SUB_EXPR)
|
M68kBinarySubExprImpl(BINARY_SUB_EXPR)
|
||||||
M68kRefExprImpl(REF_EXPR)
|
M68kRefExprImpl(REF_EXPR)
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ Assembly File: a.asm
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kStatementImpl(STATEMENT)
|
M68kStatementImpl(STATEMENT)
|
||||||
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
|
||||||
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('IF')
|
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
|
||||||
|
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('IF')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
M68kBinaryCmpEqExprImpl(BINARY_CMP_EQ_EXPR)
|
M68kBinaryCmpEqExprImpl(BINARY_CMP_EQ_EXPR)
|
||||||
M68kRefExprImpl(REF_EXPR)
|
M68kRefExprImpl(REF_EXPR)
|
||||||
|
|||||||
Reference in New Issue
Block a user