User: joe Date: 11 Nov 26 23:50 Revision: cbd0999163ddd7aa30b9a226cf1a7ad3648e4b05 Summary: Fully qualify parameter types in auto-completion TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=10718&personal=false Index: src/main/kotlin/platform/fabric/annotater/javadoc/AnnotaterJavadocCompletionContributor.kt =================================================================== --- src/main/kotlin/platform/fabric/annotater/javadoc/AnnotaterJavadocCompletionContributor.kt (revision cbd0999163ddd7aa30b9a226cf1a7ad3648e4b05) +++ src/main/kotlin/platform/fabric/annotater/javadoc/AnnotaterJavadocCompletionContributor.kt (revision cbd0999163ddd7aa30b9a226cf1a7ad3648e4b05) @@ -0,0 +1,84 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 minecraft-dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, version 3.0 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.demonwav.mcdev.platform.fabric.annotater.javadoc + +import com.intellij.codeInsight.completion.CompletionContributor +import com.intellij.codeInsight.completion.CompletionParameters +import com.intellij.codeInsight.completion.CompletionResultSet +import com.intellij.codeInsight.completion.InsertionContext +import com.intellij.codeInsight.lookup.LookupElement +import com.intellij.codeInsight.lookup.LookupElementDecorator +import com.intellij.psi.PsiMethod +import com.intellij.psi.javadoc.PsiDocComment +import com.intellij.psi.javadoc.PsiMarkdownReferenceLink +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.psi.util.TypeConversionUtil + +/** + * Keeps the parameter types of methods completed in annotater Javadocs fully qualified. + */ +class AnnotaterJavadocCompletionContributor : CompletionContributor() { + override fun fillCompletionVariants(parameters: CompletionParameters, result: CompletionResultSet) { + if (AnnotaterJavadocVirtualFile.of(parameters.originalFile) == null) { + return + } + val comment = PsiTreeUtil.getParentOfType(parameters.position, PsiDocComment::class.java) ?: return + if (!comment.isMarkdownComment) { + return + } + result.runRemainingContributors(parameters) { completion -> + result.passResult(completion.withLookupElement(QualifiedParametersLookupElement(completion.lookupElement))) + } + } + + /** + * Java's own insertion shortens the parameter types, since it doesn't recognize references in Markdown doc comments + * as being in a doc comment. They're replaced within the parentheses, so the template Java starts for the + * parameters keeps working. + */ + private class QualifiedParametersLookupElement(delegate: LookupElement) : + LookupElementDecorator(delegate) { + override fun handleInsert(context: InsertionContext) { + super.handleInsert(context) + val method = psiElement as? PsiMethod ?: return + val text = context.document.charsSequence + val open = context.startOffset + method.name.length + if (!text.startsWith(method.name, context.startOffset) || text.getOrNull(open) != '(') { + return + } + val close = text.indexOf(')', open) + if (close == -1) { + return + } + context.commitDocument() + val inLink = PsiTreeUtil.getParentOfType( + context.file.findElementAt(context.startOffset), + PsiMarkdownReferenceLink::class.java, + ) != null + val parameters = method.parameterList.parameters.joinToString(", ") { parameter -> + val type = TypeConversionUtil.erasure(parameter.type).canonicalText + // Brackets would end the link + if (inLink) type.replace("[", "\\[").replace("]", "\\]") else type + } + context.document.replaceString(open + 1, close, parameters) + } + } +} Index: src/main/resources/META-INF/plugin.xml =================================================================== --- src/main/resources/META-INF/plugin.xml (revision 1899b395231d9f2d17f4feb766ef150856efe018) +++ src/main/resources/META-INF/plugin.xml (revision cbd0999163ddd7aa30b9a226cf1a7ad3648e4b05) @@ -715,6 +715,8 @@ implementation="com.demonwav.mcdev.platform.fabric.annotater.javadoc.AnnotaterJavadocEditorNotificationProvider"/> + ticker, String[] names, int count) { + return true; - } + } + } """.trimIndent(), ) } @@ -135,6 +143,15 @@ } } + /** + * Tests use temporary code style settings, which code style settings modifiers aren't applied to. + */ + private fun withAnnotaterCodeStyle(action: () -> Unit) { + val settings = TransientCodeStyleSettings(fixture.file.virtualFile, project, CodeStyle.getSettings(project)) + AnnotaterJavadocCodeStyleSettingsModifier().modifySettings(settings, fixture.file) + CodeStyle.doWithTemporarySettings(project, settings, Runnable(action)) + } + private val pi = AnnotaterJavadocTarget.FieldTarget("net/minecraft/util/Mth", "PI", "F") private fun clampCopy(javadoc: String?, placeholderFor: AnnotaterJavadocTarget? = null) = @@ -428,6 +445,29 @@ } @Test + @DisplayName("Method completion inserts fully qualified parameter types") + fun methodParameterCompletion() { + val copy = clampCopy("See [net.minecraft.world.level.Level#addEn].") + fixture.openFileInEditor(AnnotaterJavadocVirtualFile(checkout, copy, clamp)) + fixture.editor.caretModel.moveToOffset(fixture.editor.document.text.indexOf("#addEn]") + 6) + TemplateManagerImpl.setTemplateTesting(fixture.testRootDisposable) + withAnnotaterCodeStyle { fixture.completeBasic() } + // The parameters can still be edited with the template Java starts for them + val templateState = TemplateManagerImpl.getTemplateState(fixture.editor) + assertNotNull(templateState) + val parameters = fixture.editor.document.getText(templateState!!.getVariableRange("PARAMETERS")!!) + assertTrue(parameters.contains("net.minecraft.util.Ticker, java.lang.String\\[\\], int"), parameters) + templateState.gotoEnd(false) + val text = fixture.editor.document.text + assertTrue( + text.contains( + "See [net.minecraft.world.level.Level#addEntity(net.minecraft.util.Ticker, java.lang.String\\[\\], int)].", + ), + text, + ) + } + + @Test @DisplayName("Quick documentation shows the annotater Javadoc instead of the existing one") fun quickDocumentation() { val clampMethod = findMember("net.minecraft.util.Mth", "clamp")