diff options
5 files changed, 49 insertions, 25 deletions
diff --git a/src/main/kotlin/org/rust/ide/hints/parameter/RsInlayParameterHints.kt b/src/main/kotlin/org/rust/ide/hints/parameter/RsInlayParameterHints.kt index 1bee223d2..637109b24 100644 --- a/src/main/kotlin/org/rust/ide/hints/parameter/RsInlayParameterHints.kt +++ b/src/main/kotlin/org/rust/ide/hints/parameter/RsInlayParameterHints.kt @@ -9,9 +9,11 @@ import com.intellij.codeInsight.hints.InlayInfo import com.intellij.codeInsight.hints.Option import com.intellij.psi.PsiElement import org.rust.RsBundle +import org.rust.ide.hints.type.findExpandedByLeaf import org.rust.ide.utils.CallInfo import org.rust.lang.core.psi.* -import org.rust.lang.core.psi.ext.existsAfterExpansion +import org.rust.lang.core.psi.ext.childOfType +import org.rust.lang.core.psi.ext.elementType import org.rust.lang.core.psi.ext.startOffset import org.rust.lang.core.types.emptySubstitution import org.rust.stdext.buildList @@ -22,14 +24,14 @@ object RsInlayParameterHints { val smart: Boolean get() = smartOption.get() fun provideHints(elem: PsiElement): List<InlayInfo> { - val (callInfo, valueArgumentList) = when (elem) { - is RsCallExpr -> (CallInfo.resolve(elem) to elem.valueArgumentList) - is RsMethodCall -> (CallInfo.resolve(elem) to elem.valueArgumentList) - else -> return emptyList() - } - if (!elem.existsAfterExpansion) return emptyList() - if (callInfo == null) return emptyList() + val elementExpanded = findExpandedElement(elem) ?: return emptyList() + val callInfo = when (elementExpanded) { + is RsCallExpr -> CallInfo.resolve(elementExpanded) + is RsMethodCall -> CallInfo.resolve(elementExpanded) + else -> null + } ?: return emptyList() + val valueArgumentList = elem.childOfType<RsValueArgumentList>() ?: return emptyList() val hints = buildList { if (callInfo.selfParameter != null && elem is RsCallExpr) { add(callInfo.selfParameter) @@ -61,6 +63,18 @@ object RsInlayParameterHints { return hints.map { (hint, arg) -> InlayInfo("$hint:", arg.startOffset) } } + private fun findExpandedElement(element: PsiElement): PsiElement? { + val valueArgumentList = when (element) { + is RsCallExpr -> element.valueArgumentList + is RsMethodCall -> element.valueArgumentList + else -> return null + } + val valueArgumentListExpanded = valueArgumentList.findExpandedByLeaf { it.lparen } ?: return null + if (valueArgumentListExpanded == valueArgumentList) return element + if (valueArgumentListExpanded.exprList.size != valueArgumentList.exprList.size) return null + return valueArgumentListExpanded.parent.takeIf { it.elementType == element.elementType } + } + private fun onlyOneParam(hints: List<Pair<String, RsExpr>>, callInfo: CallInfo, elem: PsiElement): Boolean { if (callInfo.selfParameter != null && elem is RsCallExpr && hints.size == 2) { return true diff --git a/src/main/kotlin/org/rust/ide/hints/type/RsInlayTypeHintsProvider.kt b/src/main/kotlin/org/rust/ide/hints/type/RsInlayTypeHintsProvider.kt index 78f9d06fe..5402e1136 100644 --- a/src/main/kotlin/org/rust/ide/hints/type/RsInlayTypeHintsProvider.kt +++ b/src/main/kotlin/org/rust/ide/hints/type/RsInlayTypeHintsProvider.kt @@ -21,6 +21,7 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.util.parentOfTypes import org.rust.RsBundle import org.rust.lang.RsLanguage +import org.rust.lang.core.crate.Crate import org.rust.lang.core.macros.* import org.rust.lang.core.psi.* import org.rust.lang.core.psi.ext.* @@ -171,7 +172,7 @@ class RsInlayTypeHintsProvider : InlayHintsProvider<RsInlayTypeHintsProvider.Set if (typeReference.descendantOfTypeOrSelf<RsInferType>() == null) return } - val expandedDeclaration = declaration.getExpanded { it.let } ?: return + val expandedDeclaration = declaration.findExpandedByLeaf(crate) { it.let } ?: return if (isExpanded) testAssert { declaration == expandedDeclaration } val inferredType = expandedDeclaration.pat?.type ?: return val formalType = expandedDeclaration.typeReference?.rawType ?: return @@ -231,7 +232,7 @@ class RsInlayTypeHintsProvider : InlayHintsProvider<RsInlayTypeHintsProvider.Set } private fun presentTypeForBinding(binding: RsPatBinding, isExpanded: Boolean) { - val bindingExpanded = binding.getExpanded { it.identifier } ?: return + val bindingExpanded = binding.findExpandedByLeaf(crate) { it.identifier } ?: return if (bindingExpanded.reference.resolve()?.isConstantLike == true) return if (bindingExpanded.type is TyUnknown) return @@ -245,16 +246,6 @@ class RsInlayTypeHintsProvider : InlayHintsProvider<RsInlayTypeHintsProvider.Set val finalPresentation = presentation.withDisableAction(project) sink.addInlineElement(offset, false, finalPresentation, false) } - - private inline fun <reified T : PsiElement> T.getExpanded(getLeaf: (T) -> PsiElement): T? = - when (getCodeStatus(crate)) { - RsCodeStatus.CFG_DISABLED -> null - RsCodeStatus.ATTR_PROC_MACRO_CALL -> { - val leafExpanded = getLeaf(this).findExpansionElements()?.singleOrNull() - leafExpanded?.parent as? T - } - else -> this - } } } @@ -325,3 +316,13 @@ private fun findOriginalOffset(anchor: PsiElement, originalFile: PsiFile): Int? if (originalFile.findElementAt(offset1)?.findExpansionElements()?.size != 1) return null return offset1 } + +inline fun <reified T : PsiElement> T.findExpandedByLeaf(explicitCrate: Crate? = null, getLeaf: (T) -> PsiElement): T? = + when (getCodeStatus(explicitCrate)) { + RsCodeStatus.CFG_DISABLED -> null + RsCodeStatus.ATTR_PROC_MACRO_CALL -> { + val leafExpanded = getLeaf(this).findExpansionElements()?.singleOrNull() + leafExpanded?.parent as? T + } + else -> this + } diff --git a/src/main/resources/compiler-info/compiler-features.json b/src/main/resources/compiler-info/compiler-features.json index 42f2dd907..ba5277b0a 100644 --- a/src/main/resources/compiler-info/compiler-features.json +++ b/src/main/resources/compiler-info/compiler-features.json @@ -93,6 +93,7 @@ {"name":"min_const_generics","state":"accepted","since":"1.51.0"}, {"name":"min_const_unsafe_fn","state":"accepted","since":"1.33.0"}, {"name":"more_struct_aliases","state":"accepted","since":"1.16.0"}, + {"name":"movbe_target_feature","state":"accepted","since":"1.70.0"}, {"name":"move_ref_pattern","state":"accepted","since":"1.49.0"}, {"name":"native_link_modifiers","state":"accepted","since":"1.61.0"}, {"name":"native_link_modifiers_bundle","state":"accepted","since":"1.63.0"}, @@ -197,7 +198,6 @@ {"name":"ermsb_target_feature","state":"active","since":"1.49.0"}, {"name":"hexagon_target_feature","state":"active","since":"1.27.0"}, {"name":"mips_target_feature","state":"active","since":"1.27.0"}, - {"name":"movbe_target_feature","state":"active","since":"1.34.0"}, {"name":"powerpc_target_feature","state":"active","since":"1.27.0"}, {"name":"riscv_target_feature","state":"active","since":"1.45.0"}, {"name":"rtm_target_feature","state":"active","since":"1.35.0"}, diff --git a/src/test/kotlin/org/rust/ide/hints/parameter/RsInlayParameterHintsProviderTest.kt b/src/test/kotlin/org/rust/ide/hints/parameter/RsInlayParameterHintsProviderTest.kt index 40346d4eb..4b38937b0 100644 --- a/src/test/kotlin/org/rust/ide/hints/parameter/RsInlayParameterHintsProviderTest.kt +++ b/src/test/kotlin/org/rust/ide/hints/parameter/RsInlayParameterHintsProviderTest.kt @@ -8,11 +8,12 @@ package org.rust.ide.hints.parameter import com.intellij.codeInsight.daemon.impl.HintRenderer import com.intellij.openapi.vfs.VirtualFileFilter import org.intellij.lang.annotations.Language -import org.rust.MockAdditionalCfgOptions -import org.rust.RsTestBase -import org.rust.fileTreeFromText +import org.rust.* +import org.rust.ide.experiments.RsExperiments.PROC_MACROS import org.rust.lang.core.psi.RsMethodCall +@WithExperimentalFeatures(PROC_MACROS) +@ProjectDescriptor(WithProcMacroRustProjectDescriptor::class) class RsInlayParameterHintsProviderTest : RsTestBase() { fun `test fn args`() = checkByText(""" fn foo(arg: u32, arg2: u32) {} @@ -230,8 +231,15 @@ class RsInlayParameterHintsProviderTest : RsTestBase() { check(inlays.size == 1) } - @Suppress("UnstableApiUsage") private fun checkByText(@Language("Rust") code: String, smart: Boolean = true) { + check("fn main() {" in code) { "Please use hints inside `fn main` function - needed for testing with attr macros" } + + doTest(code, smart) + doTest(code.replace("fn main() {", "#[test_proc_macros::attr_as_is] fn main() {"), smart) + } + + @Suppress("UnstableApiUsage") + private fun doTest(@Language("Rust") code: String, smart: Boolean) { InlineFile(code.replace(HINT_COMMENT_PATTERN, "<$1/>")) RsInlayParameterHints.smartOption.set(smart) diff --git a/src/test/kotlin/org/rust/ide/hints/type/RsChainMethodTypeHintsProviderTest.kt b/src/test/kotlin/org/rust/ide/hints/type/RsChainMethodTypeHintsProviderTest.kt index 7e8958d1a..355136530 100644 --- a/src/test/kotlin/org/rust/ide/hints/type/RsChainMethodTypeHintsProviderTest.kt +++ b/src/test/kotlin/org/rust/ide/hints/type/RsChainMethodTypeHintsProviderTest.kt @@ -157,6 +157,7 @@ class RsChainMethodTypeHintsProviderTest : RsInlayTypeHintsTestBase(RsChainMetho fun `test inside attribute macro call body`() = doTest(""" $types + #[test_proc_macros::attr_as_is] fn main() { let foo = A; foo |