New: Code completion for local label definitions, suggesting undefined labels already referenced.
This commit is contained in:
+7
-13
@@ -79,18 +79,12 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
||||
)
|
||||
|
||||
backtrace.addAll(analyseFlow(register, missingBits, true, initialStatement, linesLimit) {
|
||||
PsiTreeUtil.getPrevSiblingOfType(
|
||||
it,
|
||||
M68kStatement::class.java
|
||||
)
|
||||
PsiTreeUtil.getPrevSiblingOfType(it, M68kStatement::class.java)
|
||||
})
|
||||
backtrace.reverse()
|
||||
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) {
|
||||
PsiTreeUtil.getNextSiblingOfType(
|
||||
it,
|
||||
M68kStatement::class.java
|
||||
)
|
||||
PsiTreeUtil.getNextSiblingOfType(it, M68kStatement::class.java)
|
||||
})
|
||||
|
||||
val statementRows = HtmlBuilder()
|
||||
@@ -113,7 +107,7 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
||||
var currStatement = startingStatement
|
||||
val statementLines = ArrayList<HtmlChunk>()
|
||||
val rn = register.regname
|
||||
var addAbrevDots = false
|
||||
var addAbbrevDots = false
|
||||
var lines = 0
|
||||
while (missingBits > 0) {
|
||||
val globalLabel = PsiTreeUtil.findChildOfType(currStatement, M68kGlobalLabel::class.java)
|
||||
@@ -127,17 +121,17 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
||||
currStatement = direction.invoke(currStatement) ?: break
|
||||
val currAsmInstruction = PsiTreeUtil.getChildOfType(currStatement, M68kAsmInstruction::class.java) ?: continue
|
||||
if (checkIfInstructionUsesRegister(currAsmInstruction, register)) {
|
||||
if (addAbrevDots) {
|
||||
if (addAbbrevDots) {
|
||||
++lines
|
||||
statementLines.add(createAbbreviationDots())
|
||||
}
|
||||
if (++lines > linesLimit) {
|
||||
if (!addAbrevDots) {
|
||||
if (!addAbbrevDots) {
|
||||
statementLines.add(createAbbreviationDots())
|
||||
}
|
||||
break
|
||||
}
|
||||
addAbrevDots = false
|
||||
addAbbrevDots = false
|
||||
val (_, currAdrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(currAsmInstruction) ?: continue
|
||||
|
||||
val localLabelName = PsiTreeUtil.findChildOfType(currStatement, M68kLocalLabel::class.java)?.name ?: " "
|
||||
@@ -163,7 +157,7 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
||||
.children(lineBuilder.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL))
|
||||
)
|
||||
} else {
|
||||
addAbrevDots = true
|
||||
addAbbrevDots = true
|
||||
}
|
||||
}
|
||||
return statementLines
|
||||
|
||||
@@ -55,7 +55,7 @@ object LexerUtil {
|
||||
@JvmStatic
|
||||
fun handleMacroMode(lexer: _M68kLexer): IElementType {
|
||||
if (lexer.lexerPrefs.macroParametersUnparsed) {
|
||||
lexer.yybegin(_M68kLexer.MACROCALL)
|
||||
lexer.yybegin(_M68kLexer.PLAINPARAMS)
|
||||
} else {
|
||||
lexer.yybegin(_M68kLexer.ASMOPS)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.platon42.intellij.plugins.m68k.lexer;
|
||||
|
||||
import com.intellij.lexer.FlexLexer;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
|
||||
import static com.intellij.psi.TokenType.BAD_CHARACTER;
|
||||
@@ -101,6 +102,7 @@ PLAIN_MACRO_LINE=[^;\r\n]+
|
||||
{MACRO_DEF_LEFT} { yybegin(MACRODEF); yypushback(pushbackAfterFirstToken(yytext())); return MACRO_NAME; }
|
||||
{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; }
|
||||
"." { yybegin(INSTRPART); eatOneWhitespace = false; return LOCAL_LABEL_DEF; }
|
||||
}
|
||||
|
||||
<NOSOL> {
|
||||
|
||||
@@ -123,9 +123,9 @@ private line ::= !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
|
||||
statement ::= (Assignment
|
||||
| PreprocessorDirective
|
||||
| LabelInsts)
|
||||
{pin=1 recoverWhile=statement_recover};
|
||||
{pin = 1 recoverWhile = statement_recover}
|
||||
|
||||
private statement_recover ::= !(EOL)
|
||||
private statement_recover ::= !(EOL) { consumeTokenMethod = "consumeTokenFast" }
|
||||
|
||||
SymbolDefinition ::= SYMBOLDEF {
|
||||
implements = "de.platon42.intellij.plugins.m68k.psi.M68kNamedElement"
|
||||
|
||||
@@ -62,11 +62,4 @@ object M68kAddressModeUtil {
|
||||
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()
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ object M68kPsiImplUtil {
|
||||
|
||||
// Local Label
|
||||
@JvmStatic
|
||||
fun getName(element: M68kLocalLabel): String? = element.firstChild.text
|
||||
fun getName(element: M68kLocalLabel): String = element.firstChild?.text ?: ""
|
||||
|
||||
@JvmStatic
|
||||
fun setName(element: M68kLocalLabel, name: String): PsiElement {
|
||||
|
||||
+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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user