Added M68kIncludeFileProvider, but dunno what it's actually for.

This commit is contained in:
Chris Hodges 2021-08-06 12:16:11 +02:00
parent ddf78ec210
commit 8d7977927f
24 changed files with 199 additions and 35 deletions

View File

@ -817,14 +817,14 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
// Label? PreprocessorKeyword
// PreprocessorOperands?
public static boolean PreprocessorDirective(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PreprocessorDirective")) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, PREPROCESSOR_DIRECTIVE, "<preprocessor directive>");
r = PreprocessorDirective_0(b, l + 1);
r = r && PreprocessorDirective_1(b, l + 1);
r = r && PreprocessorKeyword(b, l + 1);
r = r && PreprocessorDirective_2(b, l + 1);
exit_section_(b, l, m, r, false, null);
return r;
@ -837,15 +837,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true;
}
// DATA_DIRECTIVE | OTHER_DIRECTIVE
private static boolean PreprocessorDirective_1(PsiBuilder b, int l) {
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;
@ -853,6 +844,19 @@ public class M68kParser implements PsiParser, LightPsiParser {
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
static boolean PreprocessorOperand(PsiBuilder b, int l) {

View File

@ -14,6 +14,9 @@ public interface M68kPreprocessorDirective extends M68kPsiElement {
@Nullable
M68kLocalLabel getLocalLabel();
@NotNull
M68kPreprocessorKeyword getPreprocessorKeyword();
@NotNull
List<M68kExpr> getExprList();

View File

@ -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 {
}

View File

@ -58,6 +58,7 @@ public interface M68kTypes {
IElementType OPERAND_SIZE = new M68kElementType("OPERAND_SIZE");
IElementType PAREN_EXPR = new M68kElementType("PAREN_EXPR");
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_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");
@ -233,6 +234,8 @@ public interface M68kTypes {
return new M68kParenExprImpl(node);
} else if (type == PREPROCESSOR_DIRECTIVE) {
return new M68kPreprocessorDirectiveImpl(node);
} else if (type == PREPROCESSOR_KEYWORD) {
return new M68kPreprocessorKeywordImpl(node);
} else if (type == PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_NEW_ADDRESSING_MODE) {
return new M68kProgramCounterIndirectWithDisplacementNewAddressingModeImpl(node);
} else if (type == PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT_OLD_ADDRESSING_MODE) {

View File

@ -131,6 +131,10 @@ public class M68kVisitor extends PsiElementVisitor {
visitPsiElement(o);
}
public void visitPreprocessorKeyword(@NotNull M68kPreprocessorKeyword o) {
visitPsiElement(o);
}
public void visitProgramCounterIndirectWithDisplacementNewAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementNewAddressingMode o) {
visitAddressingMode(o);
// visitWithDisplacement(o);

View File

@ -39,6 +39,12 @@ public class M68kPreprocessorDirectiveImpl extends ASTWrapperPsiElement implemen
return PsiTreeUtil.getChildOfType(this, M68kLocalLabel.class);
}
@Override
@NotNull
public M68kPreprocessorKeyword getPreprocessorKeyword() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kPreprocessorKeyword.class));
}
@Override
@NotNull
public List<M68kExpr> getExprList() {

View File

@ -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);
}
}

View File

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

View File

@ -72,4 +72,13 @@ object LexerUtil {
lexer.yybegin(_M68kLexer.MACROLINE)
return TokenType.WHITE_SPACE
}
fun unquoteString(string: String) = string.run {
when {
startsWith('"') -> removeSurrounding("\"")
startsWith('\'') -> removeSurrounding("'")
startsWith('<') -> removeSurrounding("<", ">")
else -> this
}
}
}

View File

@ -173,7 +173,9 @@ AsmOp ::= MNEMONIC OperandSize? {
methods = [getMnemonic getOpSize]
}
PreprocessorDirective ::= Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
PreprocessorKeyword ::= (DATA_DIRECTIVE | OTHER_DIRECTIVE)
PreprocessorDirective ::= Label? PreprocessorKeyword
PreprocessorOperands?
MacroPlainLine ::= MACRO_LINE

View File

@ -2,21 +2,13 @@ package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.lang.ASTNode
import de.platon42.intellij.plugins.m68k.lexer.LexerUtil
abstract class M68kLiteralExprMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kLiteralExpr {
override fun getValue(): Any? {
val childNode = firstChild.node
when (childNode.elementType) {
M68kTypes.STRINGLIT -> {
return text.run {
when {
startsWith('"') -> removeSurrounding("\"")
startsWith('\'') -> removeSurrounding("'")
startsWith('<') -> removeSurrounding(">")
else -> this
}
}
}
M68kTypes.STRINGLIT -> LexerUtil.unquoteString(childNode.text)
M68kTypes.DECIMAL -> {
try {
return childNode.text.toInt()
@ -46,6 +38,6 @@ abstract class M68kLiteralExprMixin(node: ASTNode) : ASTWrapperPsiElement(node),
}
}
}
return text
return childNode.text
}
}

View File

@ -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()
}
}

View File

@ -46,6 +46,7 @@
<psi.referenceContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>
<include.provider implementation="de.platon42.intellij.plugins.m68k.scanner.M68kIncludeFileProvider"/>
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kSyntaxInspection"
displayName="Assembly instruction validity" groupName="M68k"

View File

@ -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")
}
}

View File

@ -5,7 +5,8 @@ Assembly File: a.asm
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('foo')
PsiElement(M68kTokenType.COLON)(':')
PsiWhiteSpace(' ')
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.b')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.b')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)(''It could be good!'')

View File

@ -2,7 +2,8 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.w')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.w')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.DECIMAL)('0')

View File

@ -2,7 +2,8 @@ Assembly File: a.asm
PsiWhiteSpace('\t')
M68kStatementImpl(STATEMENT)
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
PsiElement(M68kTokenType.DATA_DIRECTIVE)('even')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.DATA_DIRECTIVE)('even')
PsiWhiteSpace(' ')
PsiComment(M68kTokenType.COMMENT)('; align to even address')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -2,7 +2,8 @@ Assembly File: a.asm
PsiWhiteSpace('\t')
M68kStatementImpl(STATEMENT)
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('IFD')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('IFD')
PsiWhiteSpace(' ')
M68kRefExprImpl(REF_EXPR)
M68kSymbolReferenceImpl(SYMBOL_REFERENCE)
@ -19,5 +20,6 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('ENDC')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('ENDC')
PsiElement(M68kTokenType.EOL)('\n')

View File

@ -2,7 +2,8 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('include')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('include')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('"exec/execbase.i"')

View File

@ -4,7 +4,8 @@ Assembly File: a.asm
M68kGlobalLabelImpl(GLOBAL_LABEL)
PsiElement(M68kTokenType.GLOBAL_LABEL_DEF)('howto')
PsiElement(M68kTokenType.COLON)(':')
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('incbin')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('incbin')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('Convertedassets\scroller_howto.raw.BPL')

View File

@ -2,7 +2,8 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('include')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('include')
PsiWhiteSpace('\t')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('<Engine/A500/System/Copper.i>')

View File

@ -2,7 +2,8 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('opt')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('opt')
PsiWhiteSpace(' ')
M68kLiteralExprImpl(LITERAL_EXPR)
PsiElement(M68kTokenType.STRINGLIT)('o+')

View File

@ -2,7 +2,8 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.w')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.DATA_DIRECTIVE)('dc.w')
PsiWhiteSpace(' ')
M68kBinarySubExprImpl(BINARY_SUB_EXPR)
M68kRefExprImpl(REF_EXPR)

View File

@ -2,7 +2,8 @@ Assembly File: a.asm
PsiWhiteSpace(' ')
M68kStatementImpl(STATEMENT)
M68kPreprocessorDirectiveImpl(PREPROCESSOR_DIRECTIVE)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('IF')
M68kPreprocessorKeywordImpl(PREPROCESSOR_KEYWORD)
PsiElement(M68kTokenType.OTHER_DIRECTIVE)('IF')
PsiWhiteSpace(' ')
M68kBinaryCmpEqExprImpl(BINARY_CMP_EQ_EXPR)
M68kRefExprImpl(REF_EXPR)