Skip to content

Commit

Permalink
Expressions: Add intention action to define unresolved identifiers.
Browse files Browse the repository at this point in the history
  • Loading branch information
LlamaLad7 committed Jul 9, 2024
1 parent a4769e3 commit 95fab6f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 5 deletions.
49 changes: 49 additions & 0 deletions src/main/kotlin/platform/mixin/expression/MEExpressionAnnotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,24 @@ import com.demonwav.mcdev.platform.mixin.expression.gen.psi.METype
import com.demonwav.mcdev.platform.mixin.expression.psi.METypeUtil
import com.demonwav.mcdev.platform.mixin.util.MixinConstants
import com.demonwav.mcdev.util.findMultiInjectionHost
import com.intellij.codeInsight.AutoPopupController
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.RemoveAnnotationQuickFix
import com.intellij.lang.annotation.AnnotationBuilder
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.Annotator
import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiModifierListOwner
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageEditorUtil
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.psi.util.TypeConversionUtil
import com.intellij.psi.util.parentOfType
Expand Down Expand Up @@ -275,6 +283,7 @@ class MEExpressionAnnotator : Annotator {
)
.range(type)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL)
.withDefinitionFix(type)
.create()
} else {
holder.newSilentAnnotation(HighlightSeverity.TEXT_ATTRIBUTES)
Expand Down Expand Up @@ -306,6 +315,7 @@ class MEExpressionAnnotator : Annotator {
)
.range(variable)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL)
.withDefinitionFix(variable)
.create()
} else {
holder.newSilentAnnotation(HighlightSeverity.TEXT_ATTRIBUTES)
Expand All @@ -314,4 +324,43 @@ class MEExpressionAnnotator : Annotator {
.create()
}
}

private fun AnnotationBuilder.withDefinitionFix(name: MEName) =
withFix(AddDefinitionInspection(name))

private class AddDefinitionInspection(name: MEName) : LocalQuickFixAndIntentionActionOnPsiElement(name) {
private val id = name.text

override fun getFamilyName(): String = "Add @Definition"

override fun getText(): String = "$familyName(id = \"$id\")"

override fun invoke(
project: Project,
file: PsiFile,
editor: Editor?,
startElement: PsiElement,
endElement: PsiElement
) {
if (editor == null) {
MEExpressionCompletionUtil.addDefinition(
startElement,
id,
""
)
return
}
val annotation = MEExpressionCompletionUtil.addDefinition(
startElement,
id,
"dummy"
) ?: return
val dummy = annotation.findAttribute("dummy") as? PsiElement ?: return
val hostEditor = InjectedLanguageEditorUtil.getTopLevelEditor(editor)
hostEditor.caretModel.moveToOffset(dummy.textOffset)
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(hostEditor.document)
hostEditor.document.replaceString(dummy.textRange.startOffset, dummy.textRange.endOffset, "")
AutoPopupController.getInstance(project).autoPopupMemberLookup(hostEditor, null)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,11 @@ object MEExpressionCompletionUtil {

private fun addDefinition(context: InsertionContext, id: String, definitionValue: String): PsiAnnotation? {
val contextElement = context.file.findElementAt(context.startOffset) ?: return null
return addDefinition(contextElement, id, definitionValue)
}

fun addDefinition(contextElement: PsiElement, id: String, definitionValue: String): PsiAnnotation? {
val project = contextElement.project
val injectionHost = contextElement.findMultiInjectionHost() ?: return null
val expressionAnnotation = injectionHost.parentOfType<PsiAnnotation>() ?: return null
if (!expressionAnnotation.hasQualifiedName(MixinConstants.MixinExtras.EXPRESSION)) {
Expand All @@ -1195,14 +1200,14 @@ object MEExpressionCompletionUtil {
}

// create and add the new @Definition annotation
var newAnnotation = JavaPsiFacade.getElementFactory(context.project).createAnnotationFromText(
var newAnnotation = JavaPsiFacade.getElementFactory(project).createAnnotationFromText(
"@${MixinConstants.MixinExtras.DEFINITION}(id = \"$id\", $definitionValue)",
modifierList,
)
var anchor = modifierList.annotations.lastOrNull { it.hasQualifiedName(MixinConstants.MixinExtras.DEFINITION) }
if (anchor == null) {
val definitionPosRelativeToExpression =
MinecraftProjectSettings.getInstance(context.project).definitionPosRelativeToExpression
MinecraftProjectSettings.getInstance(project).definitionPosRelativeToExpression
if (definitionPosRelativeToExpression == BeforeOrAfter.AFTER) {
anchor = expressionAnnotation
}
Expand All @@ -1211,11 +1216,11 @@ object MEExpressionCompletionUtil {

// add imports and reformat
newAnnotation =
JavaCodeStyleManager.getInstance(context.project).shortenClassReferences(newAnnotation) as PsiAnnotation
JavaCodeStyleManager.getInstance(context.project).optimizeImports(modifierList.containingFile)
JavaCodeStyleManager.getInstance(project).shortenClassReferences(newAnnotation) as PsiAnnotation
JavaCodeStyleManager.getInstance(project).optimizeImports(modifierList.containingFile)
val annotationIndex = modifierList.annotations.indexOf(newAnnotation)
val formattedModifierList =
CodeStyleManager.getInstance(context.project).reformat(modifierList) as PsiModifierList
CodeStyleManager.getInstance(project).reformat(modifierList) as PsiModifierList
return formattedModifierList.annotations.getOrNull(annotationIndex)
}

Expand Down

0 comments on commit 95fab6f

Please sign in to comment.