Skip to content

Commit

Permalink
T: Tests for substitution types in completion variants
Browse files Browse the repository at this point in the history
  • Loading branch information
mchernyavsky committed Aug 6, 2019
1 parent fa9415d commit 596612e
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package org.rust.lang.core.completion

import com.google.common.annotations.VisibleForTesting
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.patterns.ElementPattern
Expand Down Expand Up @@ -58,6 +59,24 @@ object RsCommonCompletionProvider : CompletionProvider<CompletionParameters>() {
isSimplePath = simplePathPattern.accepts(parameters.position)
)

addCompletionVariants(element, result, context, processedPathNames)

if (element is RsMethodOrField) {
addMethodAndFieldCompletion(element, result, context)
}

if (context.isSimplePath && RsCodeInsightSettings.getInstance().suggestOutOfScopeItems) {
addCompletionsFromIndex(parameters, result, processedPathNames, context.expectedTy)
}
}

@VisibleForTesting
fun addCompletionVariants(
element: RsReferenceElement,
result: CompletionResultSet,
context: RsCompletionContext,
processedPathNames: MutableSet<String>
) {
collectCompletionVariants(result, context) {
when (element) {
is RsAssocTypeBinding -> processAssocTypeVariants(element, it)
Expand Down Expand Up @@ -91,17 +110,10 @@ object RsCommonCompletionProvider : CompletionProvider<CompletionParameters>() {
}
}
}

if (element is RsMethodOrField) {
addMethodAndFieldCompletion(element, result, context)
}

if (context.isSimplePath && RsCodeInsightSettings.getInstance().suggestOutOfScopeItems) {
addCompletionsFromIndex(parameters, result, processedPathNames, context.expectedTy)
}
}

private fun addMethodAndFieldCompletion(
@VisibleForTesting
fun addMethodAndFieldCompletion(
element: RsMethodOrField,
result: CompletionResultSet,
context: RsCompletionContext
Expand Down
176 changes: 176 additions & 0 deletions src/test/kotlin/org/rust/lang/core/completion/RsLookupElementTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,23 @@

package org.rust.lang.core.completion

import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.completion.CompletionSorter
import com.intellij.codeInsight.completion.PrefixMatcher
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.patterns.ElementPattern
import com.intellij.psi.NavigatablePsiElement
import org.intellij.lang.annotations.Language
import org.rust.RsTestBase
import org.rust.lang.core.psi.RsFile
import org.rust.lang.core.psi.RsTupleFieldDecl
import org.rust.lang.core.psi.ext.RsElement
import org.rust.lang.core.psi.ext.RsMethodOrField
import org.rust.lang.core.psi.ext.RsNamedElement
import org.rust.lang.core.psi.ext.RsReferenceElement
import org.rust.lang.core.resolve.SimpleScopeEntry
import org.rust.lang.core.types.implLookup

class RsLookupElementTest : RsTestBase() {
fun `test fn`() = check("""
Expand Down Expand Up @@ -147,6 +155,131 @@ class RsLookupElementTest : RsTestBase() {
assertEquals("foo", presentation.itemText)
}

fun `test generic field`() = checkProvider("""
struct S<A> { foo: A }
fn main() {
let s = S { foo: 0 };
s.foo;
//^
}
""", typeText = "i32")

fun `test generic method (impl)`() = checkProvider("""
struct S<A>(A);
impl <B> S<B> {
fn foo(&self, x: B) -> B { x }
}
fn main() {
let s = S(0);
s.foo;
//^
}
""", tailText = "(&self, x: i32)", typeText = "i32")

fun `test generic method (trait)`() = checkProvider("""
struct S<A>(A);
trait T<B> {
fn foo(&self, x: B) -> B { x }
}
impl <C> T<C> for S<C> {
}
fn main() {
let s = S(0);
s.foo;
//^
}
""", tailText = "(&self, x: i32)", typeText = "i32")

fun `test generic method (impl trait)`() = checkProvider("""
struct S<A>(A);
trait T<B> {
fn foo(&self, x: B) -> B;
}
impl <C> T<C> for S<C> {
fn foo(&self, x: C) -> C { x }
}
fn main() {
let s = S(0);
s.foo;
//^
}
""", tailText = "(&self, x: i32) of T<i32>", typeText = "i32")

fun `test generic method (dyn)`() = checkProvider("""
struct S<A>(A);
trait T<B> {
fn foo(&self, x: B) -> B;
}
impl <C> T<C> for &S<C> {
fn foo(&self, x: C) -> C { x }
}
fn main() {
let s = S(0);
let d: &dyn T<i32> = &&s;
d.foo;
//^
}
""", tailText = "(&self, x: i32)", typeText = "i32")

fun `test generic function (impl)`() = checkProvider("""
struct S<A>(A);
impl <B> S<B> {
fn foo(x: B) -> B { x }
}
fn main() {
S::<i32>::foo;
//^
}
""", tailText = "(x: i32)", typeText = "i32")

fun `test generic function (trait)`() = checkProvider("""
struct S<A>(A);
trait T<B> {
fn foo(x: B) -> B { x }
}
impl <C> T<C> for S<C> {
}
fn main() {
S::<i32>::foo;
//^
}
""", tailText = "(x: i32)", typeText = "i32")

fun `test generic function (impl trait)`() = checkProvider("""
struct S<A>(A);
trait T<B> {
fn foo(x: B) -> B;
}
impl <C> T<C> for S<C> {
fn foo(x: C) -> C { x }
}
fn main() {
S::<i32>::foo;
//^
}
""", tailText = "(x: i32) of T<i32>", typeText = "i32")

private fun check(
@Language("Rust") code: String,
tailText: String? = null,
Expand Down Expand Up @@ -174,4 +307,47 @@ class RsLookupElementTest : RsTestBase() {
assertEquals(typeText, presentation.typeText)
assertEquals(isStrikeout, presentation.isStrikeout)
}

private fun checkProvider(
@Language("Rust") code: String,
tailText: String? = null,
typeText: String? = null,
isStrikeout: Boolean = false
) {
InlineFile(code)
val element = findElementInEditor<RsReferenceElement>()
val context = RsCompletionContext(element.implLookup)
val processedPathNames = mutableSetOf<String>()

val lookups = mutableListOf<LookupElement>()
val result = object : CompletionResultSet(PrefixMatcher.ALWAYS_TRUE, null, null) {
override fun caseInsensitive(): CompletionResultSet = this
override fun withPrefixMatcher(matcher: PrefixMatcher): CompletionResultSet = this
override fun withPrefixMatcher(prefix: String): CompletionResultSet = this
override fun restartCompletionOnPrefixChange(prefixCondition: ElementPattern<String>?) {}
override fun addLookupAdvertisement(text: String) {}
override fun withRelevanceSorter(sorter: CompletionSorter): CompletionResultSet = this
override fun restartCompletionWhenNothingMatches() {}
override fun addElement(element: LookupElement) {
lookups.add(element)
}
}

RsCommonCompletionProvider.addCompletionVariants(element, result, context, processedPathNames)
if (element is RsMethodOrField) {
RsCommonCompletionProvider.addMethodAndFieldCompletion(element, result, context)
}

val lookup = lookups.single {
val namedElement = it.psiElement as? RsNamedElement
namedElement?.name == element.referenceName
}
val presentation = LookupElementPresentation()
lookup.renderElement(presentation)

assertNotNull(presentation.icon)
assertEquals(tailText, presentation.tailText)
assertEquals(typeText, presentation.typeText)
assertEquals(isStrikeout, presentation.isStrikeout)
}
}

0 comments on commit 596612e

Please sign in to comment.