diff --git a/idea/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt b/idea/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt index aa86a886755..cb62862e2c2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt @@ -20,47 +20,30 @@ import com.intellij.codeInsight.completion.* import com.intellij.openapi.editor.Document import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.patterns.PlatformPatterns -import com.intellij.util.ProcessingContext -import org.jetbrains.kotlin.psi.JetBlockExpression -import org.jetbrains.kotlin.psi.JetCallExpression -import org.jetbrains.kotlin.psi.JetExpression -import org.jetbrains.kotlin.psi.JetFile -import org.jetbrains.kotlin.lexer.JetTokens -import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion - import com.intellij.patterns.PsiJavaPatterns.elementType import com.intellij.patterns.PsiJavaPatterns.psiElement +import com.intellij.psi.PsiComment import com.intellij.psi.PsiElement +import com.intellij.psi.PsiErrorElement +import com.intellij.psi.TokenType +import com.intellij.psi.search.PsiElementProcessor import com.intellij.psi.tree.TokenSet import com.intellij.psi.util.PsiTreeUtil -import com.intellij.psi.TokenType -import org.jetbrains.kotlin.psi.JetNameReferenceExpression -import org.jetbrains.kotlin.psi.JetUserType -import org.jetbrains.kotlin.psi.JetTypeReference -import org.jetbrains.kotlin.psi.JetNamedFunction -import org.jetbrains.kotlin.psi.JetProperty -import org.jetbrains.kotlin.psi.JetPsiFactory -import com.intellij.psi.PsiErrorElement -import com.intellij.psi.search.PsiElementProcessor -import com.intellij.psi.PsiComment -import org.jetbrains.kotlin.psi.psiUtil.parents -import org.jetbrains.kotlin.psi.JetParameterList -import org.jetbrains.kotlin.psi.JetFunctionLiteral -import org.jetbrains.kotlin.psi.psiUtil.prevLeafSkipWhitespacesAndComments -import org.jetbrains.kotlin.psi.JetValueArgument -import org.jetbrains.kotlin.psi.JetValueArgumentList -import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType -import org.jetbrains.kotlin.psi.psiUtil.prevLeaf -import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.psi.JetTypeArgumentList -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import com.intellij.util.ProcessingContext import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion +import org.jetbrains.kotlin.lexer.JetTokens +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.psi.psiUtil.parents +import org.jetbrains.kotlin.psi.psiUtil.prevLeaf +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.psi.JetTypeElement -import org.jetbrains.kotlin.psi.JetAnnotationEntry +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull public class KotlinCompletionContributor : CompletionContributor() { @@ -93,6 +76,8 @@ public class KotlinCompletionContributor : CompletionContributor() { isInFunctionLiteralParameterList(tokenBefore) -> CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED + isInClassHeader(tokenBefore) -> CompletionUtilCore.DUMMY_IDENTIFIER // do not add '$' to not interrupt class declaration parsing + else -> specialExtensionReceiverDummyIdentifier(tokenBefore) ?: specialInTypeArgsDummyIdentifier(tokenBefore) ?: specialInParameterListDummyIdentifier(tokenBefore) @@ -146,6 +131,14 @@ public class KotlinCompletionContributor : CompletionContributor() { return parent is JetFunctionLiteral && parent.getValueParameterList() == parameterList } + private fun isInClassHeader(tokenBefore: PsiElement?): Boolean { + val classOrObject = tokenBefore?.parents(false)?.firstIsInstanceOrNull() ?: return false + val name = classOrObject.getNameIdentifier() ?: return false + val body = classOrObject.getBody() ?: return false + val offset = tokenBefore!!.getTextRange().getStartOffset() + return name.getTextRange().getEndOffset() <= offset && offset <= body.getTextRange().getStartOffset() + } + private val declarationKeywords = TokenSet.create(JetTokens.FUN_KEYWORD, JetTokens.VAL_KEYWORD, JetTokens.VAR_KEYWORD) private val declarationTokens = TokenSet.orSet(TokenSet.create(JetTokens.IDENTIFIER, JetTokens.LT, JetTokens.GT, JetTokens.COMMA, JetTokens.DOT, JetTokens.QUEST, JetTokens.COLON, diff --git a/idea/testData/completion/basic/common/NestedClassBug.kt b/idea/testData/completion/basic/common/NestedClassBug.kt new file mode 100644 index 00000000000..18dd6ebd85d --- /dev/null +++ b/idea/testData/completion/basic/common/NestedClassBug.kt @@ -0,0 +1,7 @@ +package ppp + +class Base(p: Base.N) { + class Nested +} + +// EXIST: { lookupString: "Nested", itemText: "Nested", tailText: " (ppp.Base)" } diff --git a/idea/tests/org/jetbrains/kotlin/completion/JSBasicCompletionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/completion/JSBasicCompletionTestGenerated.java index 93e92afd815..27f4fc04eff 100644 --- a/idea/tests/org/jetbrains/kotlin/completion/JSBasicCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/completion/JSBasicCompletionTestGenerated.java @@ -601,6 +601,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("NestedClassBug.kt") + public void testNestedClassBug() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/NestedClassBug.kt"); + doTest(fileName); + } + @TestMetadata("NestedClassNameForExtension.kt") public void testNestedClassNameForExtension() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/NestedClassNameForExtension.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/completion/JvmBasicCompletionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/completion/JvmBasicCompletionTestGenerated.java index 3e7f16788c6..d8993275d13 100644 --- a/idea/tests/org/jetbrains/kotlin/completion/JvmBasicCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/completion/JvmBasicCompletionTestGenerated.java @@ -601,6 +601,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("NestedClassBug.kt") + public void testNestedClassBug() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/NestedClassBug.kt"); + doTest(fileName); + } + @TestMetadata("NestedClassNameForExtension.kt") public void testNestedClassNameForExtension() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/NestedClassNameForExtension.kt");