From 5fb9aae68c1154517aa544cb938716fb469e27e0 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 13 Aug 2014 22:39:09 +0400 Subject: [PATCH] Escaping of keyword names in completion (more tests to be added) --- .../jet/lang/resolve/ImportPath.java | 3 +- .../jet/renderer/DescriptorRenderer.java | 9 +++ .../jet/renderer/DescriptorRendererImpl.java | 6 +- .../KotlinCopyPasteReferenceProcessor.kt | 6 +- .../jet/plugin/completion/CompletionUtils.kt | 19 ++++++ .../completion/DescriptorLookupConverter.kt | 10 ++-- .../completion/NamedParametersCompletion.kt | 7 +-- .../handlers/BaseDeclarationInsertHandler.kt | 38 ++++++++++++ .../handlers/JetClassInsertHandler.kt | 59 +++++++------------ .../handlers/JetFunctionInsertHandler.kt | 5 +- .../plugin/completion/smart/StaticMembers.kt | 5 +- .../jet/plugin/completion/smart/ThisItems.kt | 13 ++-- .../smart/TypeInstantiationItems.kt | 7 +-- .../completion/handlers/KeywordClassName.kt | 5 ++ .../handlers/KeywordClassName.kt.after | 5 ++ .../KeywordExtensionFunctionName-1.kt | 5 ++ .../KeywordExtensionFunctionName-2.kt | 3 + .../KeywordExtensionFunctionName.kt.after | 7 +++ .../handlers/BasicCompletionHandlerTest.kt | 2 + .../CompletionMultifileHandlerTest.java | 4 ++ 20 files changed, 151 insertions(+), 67 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/handlers/BaseDeclarationInsertHandler.kt create mode 100644 idea/testData/completion/handlers/KeywordClassName.kt create mode 100644 idea/testData/completion/handlers/KeywordClassName.kt.after create mode 100644 idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName-1.kt create mode 100644 idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName-2.kt create mode 100644 idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName.kt.after diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/ImportPath.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/ImportPath.java index 74d44af8791..42c3721229b 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/ImportPath.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/ImportPath.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.renderer.DescriptorRenderer; public final class ImportPath { private final @NotNull FqName fqName; @@ -50,7 +51,7 @@ public final class ImportPath { } public String getPathStr() { - return fqName.asString() + (isAllUnder ? ".*" : ""); + return DescriptorRenderer.SOURCE_CODE.renderFqName(fqName) + (isAllUnder ? ".*" : ""); } @Override diff --git a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java index b1947acacfb..169eb1702a2 100644 --- a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java +++ b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java @@ -21,6 +21,9 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.name.FqNameBase; +import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; @@ -110,6 +113,12 @@ public interface DescriptorRenderer extends Renderer { @NotNull String renderFunctionParameters(@NotNull FunctionDescriptor functionDescriptor); + @NotNull + String renderName(@NotNull Name name); + + @NotNull + String renderFqName(@NotNull FqNameBase fqName); + enum TextFormat { PLAIN, HTML } diff --git a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java index 1e3646a897f..494e0c2692b 100644 --- a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java @@ -198,8 +198,9 @@ public class DescriptorRendererImpl implements DescriptorRenderer { } /* NAMES RENDERING */ + @Override @NotNull - private String renderName(@NotNull Name identifier) { + public String renderName(@NotNull Name identifier) { String asString = identifier.toString(); return escape(KeywordStringsGenerated.KEYWORDS.contains(asString) ? '`' + asString + '`' : asString); } @@ -219,8 +220,9 @@ public class DescriptorRendererImpl implements DescriptorRenderer { } } + @Override @NotNull - private String renderFqName(@NotNull FqNameBase fqName) { + public String renderFqName(@NotNull FqNameBase fqName) { return renderFqName(fqName.pathSegments()); } diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/KotlinCopyPasteReferenceProcessor.kt b/idea/src/org/jetbrains/jet/plugin/codeInsight/KotlinCopyPasteReferenceProcessor.kt index 9ef641aefb3..91807f37adc 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/KotlinCopyPasteReferenceProcessor.kt +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/KotlinCopyPasteReferenceProcessor.kt @@ -61,6 +61,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils import org.jetbrains.jet.plugin.imports.* import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression import org.jetbrains.jet.utils.* +import org.jetbrains.jet.renderer.DescriptorRenderer //NOTE: this class is based on CopyPasteReferenceProcessor and JavaCopyPasteReferenceProcessor public class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor() { @@ -322,9 +323,8 @@ public class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor qualifiedNameForSourceCode(parent) + is PackageViewDescriptor -> DescriptorRenderer.SOURCE_CODE.renderFqName(parent.getFqName()) + is PackageFragmentDescriptor -> DescriptorRenderer.SOURCE_CODE.renderFqName(parent.fqName) + else -> null + } + return if (qualifier != null && qualifier != "") qualifier + "." + nameString else nameString +} + diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.kt b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.kt index 6567a4f017c..bb94c491294 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.kt @@ -32,12 +32,14 @@ import org.jetbrains.jet.plugin.completion.handlers.GenerateLambdaInfo import org.jetbrains.jet.plugin.completion.handlers.JetClassInsertHandler import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler import org.jetbrains.jet.renderer.DescriptorRenderer +import org.jetbrains.jet.plugin.completion.handlers.BaseDeclarationInsertHandler public object DescriptorLookupConverter { public fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor, declaration: PsiElement?): LookupElement { - var element = LookupElementBuilder.create(DeclarationLookupObject(descriptor, analyzer, declaration), descriptor.getName().asString()) + val name = descriptor.getName().asString() + var element = LookupElementBuilder.create(DeclarationLookupObject(descriptor, analyzer, declaration), name) - var presentableText = descriptor.getName().asString() + var presentableText = name var typeText = "" var tailText = "" @@ -75,7 +77,7 @@ public object DescriptorLookupConverter { return element } - public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler? { + public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler { return when (descriptor) { is FunctionDescriptor -> { val parameters = descriptor.getValueParameters() @@ -100,7 +102,7 @@ public object DescriptorLookupConverter { is ClassDescriptor -> JetClassInsertHandler - else -> null + else -> BaseDeclarationInsertHandler() } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/NamedParametersCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/NamedParametersCompletion.kt index b44234087a5..b4b40310cf3 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/NamedParametersCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/NamedParametersCompletion.kt @@ -17,7 +17,6 @@ package org.jetbrains.jet.plugin.completion import org.jetbrains.jet.lang.psi.JetValueArgument -import com.intellij.codeInsight.completion.CompletionParameters import org.jetbrains.jet.lexer.JetTokens import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.jet.lang.psi.JetCallElement @@ -27,7 +26,6 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder import org.jetbrains.jet.plugin.JetIcons import org.jetbrains.jet.plugin.quickfix.QuickFixUtil import org.jetbrains.jet.renderer.DescriptorRenderer -import com.intellij.codeInsight.completion.InsertHandler import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.completion.InsertionContext import com.intellij.psi.filters.AndFilter @@ -38,6 +36,7 @@ import com.intellij.psi.filters.ClassFilter import org.jetbrains.jet.plugin.util.FirstChildInParentFilter import org.jetbrains.jet.lang.psi.psiUtil.getCallNameExpression import com.intellij.psi.PsiElement +import org.jetbrains.jet.plugin.completion.handlers.BaseDeclarationInsertHandler object NamedParametersCompletion { private val positionFilter = AndFilter( @@ -86,7 +85,7 @@ object NamedParametersCompletion { for (parameter in funDescriptor.getValueParameters()) { val name = parameter.getName().asString() if (name !in usedArguments) { - val lookupElement = LookupElementBuilder.create("$name") + val lookupElement = LookupElementBuilder.create(parameter, name) .withPresentableText("$name = ") .withTailText("${DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(parameter.getType())}") .withIcon(JetIcons.PARAMETER) @@ -100,7 +99,7 @@ object NamedParametersCompletion { } } - private object NamedParameterInsertHandler : InsertHandler { + private object NamedParameterInsertHandler : BaseDeclarationInsertHandler() { override fun handleInsert(context: InsertionContext, item: LookupElement) { val ch = context.getCompletionChar() if (ch == '=' || ch == ' ') { diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/BaseDeclarationInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/BaseDeclarationInsertHandler.kt new file mode 100644 index 00000000000..abfbea65c56 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/BaseDeclarationInsertHandler.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.completion.handlers + +import com.intellij.codeInsight.completion.InsertHandler +import com.intellij.codeInsight.lookup.LookupElement +import com.intellij.codeInsight.completion.InsertionContext +import org.jetbrains.jet.plugin.completion.DeclarationLookupObject +import org.jetbrains.jet.renderer.DescriptorRenderer +import com.intellij.openapi.util.TextRange + +open class BaseDeclarationInsertHandler : InsertHandler { + override fun handleInsert(context: InsertionContext, item: LookupElement) { + val descriptor = (item.getObject() as? DeclarationLookupObject)?.descriptor + if (descriptor != null) { + val name = descriptor.getName() + val nameInCode = DescriptorRenderer.SOURCE_CODE.renderName(name) + val document = context.getDocument() + if (nameInCode != name.asString() && document.getText(TextRange(context.getStartOffset(), context.getTailOffset())) == name.asString()) { + document.replaceString(context.getStartOffset(), context.getTailOffset(), nameInCode) + } + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.kt index 8264ac48e25..54ffe112254 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.kt @@ -16,7 +16,6 @@ package org.jetbrains.jet.plugin.completion.handlers -import com.intellij.codeInsight.completion.InsertHandler import com.intellij.codeInsight.completion.InsertionContext import com.intellij.codeInsight.lookup.LookupElement import com.intellij.openapi.editor.Document @@ -25,36 +24,34 @@ import org.jetbrains.jet.lang.psi.JetFile import org.jetbrains.jet.plugin.codeInsight.ShortenReferences import org.jetbrains.jet.plugin.completion.DeclarationLookupObject import org.jetbrains.jet.lang.descriptors.ClassDescriptor -import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor -import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor - -public object JetClassInsertHandler : InsertHandler { +import org.jetbrains.jet.plugin.completion.qualifiedNameForSourceCode +public object JetClassInsertHandler : BaseDeclarationInsertHandler() { override fun handleInsert(context: InsertionContext, item: LookupElement) { + super.handleInsert(context, item) + val file = context.getFile() if (file is JetFile) { - val descriptor = (item.getObject() as? DeclarationLookupObject)?.descriptor as? ClassDescriptor - if (descriptor != null) { - val startOffset = context.getStartOffset() - val document = context.getDocument() - if (!isAfterDot(document, startOffset)) { - val qualifiedName = getQualifiedName(descriptor)!! - // insert dot after because otherwise parser can sometimes produce no suitable reference here - val tempSuffix = ".xxx" // we add "xxx" after dot because of some bugs in resolve (see KT-5145) - document.replaceString(startOffset, context.getTailOffset(), qualifiedName + tempSuffix) - val classNameEnd = startOffset + qualifiedName.length() + val descriptor = (item.getObject() as DeclarationLookupObject).descriptor as ClassDescriptor + val startOffset = context.getStartOffset() + val document = context.getDocument() + if (!isAfterDot(document, startOffset)) { + val qualifiedName = qualifiedNameForSourceCode(descriptor)!! + // insert dot after because otherwise parser can sometimes produce no suitable reference here + val tempSuffix = ".xxx" // we add "xxx" after dot because of some bugs in resolve (see KT-5145) + document.replaceString(startOffset, context.getTailOffset(), qualifiedName + tempSuffix) + val classNameEnd = startOffset + qualifiedName.length() - val psiDocumentManager = PsiDocumentManager.getInstance(context.getProject()) - psiDocumentManager.commitAllDocuments() - val rangeMarker = document.createRangeMarker(classNameEnd, classNameEnd + tempSuffix.length()) + val psiDocumentManager = PsiDocumentManager.getInstance(context.getProject()) + psiDocumentManager.commitAllDocuments() + val rangeMarker = document.createRangeMarker(classNameEnd, classNameEnd + tempSuffix.length()) - ShortenReferences.process(file, startOffset, classNameEnd) - psiDocumentManager.commitAllDocuments() - psiDocumentManager.doPostponedOperationsAndUnblockDocument(document) + ShortenReferences.process(file, startOffset, classNameEnd) + psiDocumentManager.commitAllDocuments() + psiDocumentManager.doPostponedOperationsAndUnblockDocument(document) - if (rangeMarker.isValid()) { - document.deleteString(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()) - } + if (rangeMarker.isValid()) { + document.deleteString(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()) } } } @@ -72,18 +69,4 @@ public object JetClassInsertHandler : InsertHandler { } return false } - - private fun getQualifiedName(descriptor: ClassDescriptor): String? { - val name = descriptor.getName() - if (name.isSpecial()) return null - val nameString = name.asString() - val parent = descriptor.getContainingDeclaration() - val qualifier = when (parent) { - is ClassDescriptor -> getQualifiedName(parent) - is PackageViewDescriptor -> parent.getFqName().asString() - is PackageFragmentDescriptor -> parent.fqName.asString() - else -> null - } - return if (qualifier != null && qualifier != "") qualifier + "." + nameString else nameString - } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt index 410c9a8fc43..665e1490fcb 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt @@ -16,7 +16,6 @@ package org.jetbrains.jet.plugin.completion.handlers -import com.intellij.codeInsight.completion.InsertHandler import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.completion.InsertionContext import com.intellij.psi.PsiDocumentManager @@ -45,7 +44,7 @@ public enum class CaretPosition { public data class GenerateLambdaInfo(val lambdaType: JetType, val explicitParameters: Boolean) -public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val lambdaInfo: GenerateLambdaInfo?) : InsertHandler { +public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val lambdaInfo: GenerateLambdaInfo?) : BaseDeclarationInsertHandler() { { if (caretPosition == CaretPosition.AFTER_BRACKETS && lambdaInfo != null) { throw IllegalArgumentException("CaretPosition.AFTER_BRACKETS with lambdaInfo != null combination is not supported") @@ -53,6 +52,8 @@ public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val lam } public override fun handleInsert(context: InsertionContext, item: LookupElement) { + super.handleInsert(context, item) + PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments() if (context.getCompletionChar() == '(') { context.setAddCompletionChar(false) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt index d3b15998770..8c3ca5cbd7e 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt @@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.lang.psi.JetExpression import org.jetbrains.jet.plugin.completion.ExpectedInfo import org.jetbrains.jet.plugin.util.makeNotNullable +import org.jetbrains.jet.plugin.completion.qualifiedNameForSourceCode // adds java static members, enum members and members from class object class StaticMembers(val bindingContext: BindingContext, val resolveSession: ResolveSessionForBodies) { @@ -117,7 +118,7 @@ class StaticMembers(val bindingContext: BindingContext, val resolveSession: Reso val lookupElement = createLookupElement(memberDescriptor, resolveSession) val qualifierPresentation = classDescriptor.getName().asString() val lookupString = qualifierPresentation + "." + lookupElement.getLookupString() - val qualifierText = DescriptorUtils.getFqName(classDescriptor).asString() //TODO: escape keywords + val qualifierText = qualifiedNameForSourceCode(classDescriptor) return object: LookupElementDecorator(lookupElement) { override fun getLookupString() = lookupString @@ -141,7 +142,7 @@ class StaticMembers(val bindingContext: BindingContext, val resolveSession: Reso } override fun handleInsert(context: InsertionContext) { - var text = qualifierText + "." + memberDescriptor.getName().asString() //TODO: escape + var text = qualifierText + "." + DescriptorRenderer.SOURCE_CODE.renderName(memberDescriptor.getName()) context.getDocument().replaceString(context.getStartOffset(), context.getTailOffset(), text) context.setTailOffset(context.getStartOffset() + text.length) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/ThisItems.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/ThisItems.kt index ab54a2ed1b7..165d0093627 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/ThisItems.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/ThisItems.kt @@ -21,9 +21,6 @@ import org.jetbrains.jet.lang.psi.JetExpression import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor import com.intellij.codeInsight.lookup.LookupElementBuilder import org.jetbrains.jet.renderer.DescriptorRenderer -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor -import org.jetbrains.jet.lang.resolve.name.Name -import org.jetbrains.jet.lang.resolve.BindingContextUtils import org.jetbrains.jet.lang.psi.JetFunctionLiteral import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression import org.jetbrains.jet.lang.psi.JetObjectDeclaration @@ -65,12 +62,14 @@ class ThisItems(val bindingContext: BindingContext) { } private fun thisQualifierName(receiver: ReceiverParameterDescriptor): String? { - val descriptor: DeclarationDescriptor = receiver.getContainingDeclaration() - val name: Name = descriptor.getName() - if (!name.isSpecial()) return name.asString() + val descriptor = receiver.getContainingDeclaration() + val name = descriptor.getName() + if (!name.isSpecial()) { + return DescriptorRenderer.SOURCE_CODE.renderName(name) + } val psiElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) - val expression: JetExpression? = when (psiElement) { + val expression = when (psiElement) { is JetFunctionLiteral -> psiElement.getParent() as? JetFunctionLiteralExpression is JetObjectDeclaration -> psiElement.getParent() as? JetObjectLiteralExpression else -> null diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt index d6a0dc25a01..8ff32f528c8 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt @@ -22,14 +22,12 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns import org.jetbrains.jet.lang.descriptors.ClassDescriptor import org.jetbrains.jet.renderer.DescriptorRenderer import com.intellij.codeInsight.completion.InsertHandler -import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.lang.descriptors.Modality import org.jetbrains.jet.lang.descriptors.ClassKind import org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler import com.intellij.codeInsight.lookup.LookupElementDecorator import com.intellij.codeInsight.lookup.LookupElementPresentation import com.intellij.codeInsight.completion.InsertionContext -import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.plugin.project.ResolveSessionForBodies import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler import org.jetbrains.jet.plugin.completion.* @@ -37,6 +35,7 @@ import org.jetbrains.jet.plugin.completion.handlers.CaretPosition import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor import org.jetbrains.jet.lang.descriptors.Visibilities import org.jetbrains.jet.plugin.util.makeNotNullable +import org.jetbrains.jet.lang.resolve.DescriptorUtils class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val visibilityFilter: (DeclarationDescriptor) -> Boolean) { public fun addToCollection(collection: MutableCollection, expectedInfos: Collection) { @@ -71,7 +70,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val vi var itemText = lookupString + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderTypeArguments(typeArgs) val insertHandler: InsertHandler - val typeText = DescriptorUtils.getFqName(classifier).toString() + DescriptorRenderer.SOURCE_CODE.renderTypeArguments(typeArgs) + val typeText = qualifiedNameForSourceCode(classifier) + DescriptorRenderer.SOURCE_CODE.renderTypeArguments(typeArgs) if (isAbstract) { val constructorParenthesis = if (classifier.getKind() != ClassKind.TRAIT) "()" else "" itemText += constructorParenthesis @@ -97,7 +96,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val vi (if (visibleConstructors.size == 0) JetFunctionInsertHandler.NO_PARAMETERS_HANDLER else if (visibleConstructors.size == 1) - DescriptorLookupConverter.getDefaultInsertHandler(visibleConstructors.single())!! + DescriptorLookupConverter.getDefaultInsertHandler(visibleConstructors.single()) else JetFunctionInsertHandler.WITH_PARAMETERS_HANDLER) as JetFunctionInsertHandler insertHandler = object : InsertHandler { diff --git a/idea/testData/completion/handlers/KeywordClassName.kt b/idea/testData/completion/handlers/KeywordClassName.kt new file mode 100644 index 00000000000..6e422241914 --- /dev/null +++ b/idea/testData/completion/handlers/KeywordClassName.kt @@ -0,0 +1,5 @@ +package test + +class `class` + +fun foo(p: ) \ No newline at end of file diff --git a/idea/testData/completion/handlers/KeywordClassName.kt.after b/idea/testData/completion/handlers/KeywordClassName.kt.after new file mode 100644 index 00000000000..dea8cb90db0 --- /dev/null +++ b/idea/testData/completion/handlers/KeywordClassName.kt.after @@ -0,0 +1,5 @@ +package test + +class `class` + +fun foo(p: `class`) \ No newline at end of file diff --git a/idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName-1.kt b/idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName-1.kt new file mode 100644 index 00000000000..dd3b6800c0d --- /dev/null +++ b/idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName-1.kt @@ -0,0 +1,5 @@ +package first + +fun foo() { + "".pack +} diff --git a/idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName-2.kt b/idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName-2.kt new file mode 100644 index 00000000000..e25fb56fc27 --- /dev/null +++ b/idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName-2.kt @@ -0,0 +1,3 @@ +package second + +fun String.`package`() { } diff --git a/idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName.kt.after b/idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName.kt.after new file mode 100644 index 00000000000..7ed10ce523d --- /dev/null +++ b/idea/testData/completion/handlers/multifile/KeywordExtensionFunctionName.kt.after @@ -0,0 +1,7 @@ +package first + +import second.`package` + +fun foo() { + "".`package`() +} diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt b/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt index a1524754c6f..4d3894f6bb9 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt +++ b/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt @@ -144,4 +144,6 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){ fun testNestedLocalClassCompletion() = doTest(1, "Nested", null, '\n') fun testTypeArgOfSuper() = doTest(1, "X", null, '\n') + + fun testKeywordClassName() = doTest(1, "class", null, '\n') } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java index b30c89bc81b..6156964863b 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java +++ b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java @@ -46,6 +46,10 @@ public class CompletionMultifileHandlerTest extends KotlinCompletionTestCase { doTest(); } + public void testKeywordExtensionFunctionName() throws Exception { + doTest(); + } + public void doTest() throws Exception { String fileName = getTestName(false);