Fixed keywords after 'this@' completion + fixed implementation of JetExpressionWithLabel.getLabelName()

This commit is contained in:
Valentin Kipyatkov
2015-05-20 11:46:16 +03:00
parent 2a5ca095ee
commit a6f76bbf76
13 changed files with 56 additions and 28 deletions
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi
import com.intellij.lang.ASTNode
import org.jetbrains.kotlin.JetNodeTypes
import org.jetbrains.kotlin.name.Name
open public class JetExpressionWithLabel(node: ASTNode) : JetExpressionImpl(node) {
@@ -25,7 +26,8 @@ open public class JetExpressionWithLabel(node: ASTNode) : JetExpressionImpl(node
findChildByType<JetContainerNode>(JetNodeTypes.LABEL_QUALIFIER)?.
findChildByType(JetNodeTypes.LABEL) as? JetSimpleNameExpression
public fun getLabelName(): String? = getTargetLabel()?.getIdentifier()?.getText()
public fun getLabelName(): String? = getTargetLabel()?.getReferencedName()
public fun getLabelNameAsName(): Name? = getTargetLabel()?.getReferencedNameAsName()
override fun <R, D> accept(visitor: JetVisitor<R, D>, data: D) = visitor.visitExpressionWithLabel(this, data)
}
@@ -429,10 +429,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
ExpressionTypingContext context,
boolean onlyClassReceivers
) {
String labelName = expression.getLabelName();
Name labelName = expression.getLabelNameAsName();
if (labelName != null) {
LabelResolver.LabeledReceiverResolutionResult resolutionResult =
LabelResolver.INSTANCE.resolveThisOrSuperLabel(expression, context, Name.identifier(labelName));
LabelResolver.INSTANCE.resolveThisOrSuperLabel(expression, context, labelName);
if (resolutionResult.success()) {
ReceiverParameterDescriptor receiverParameterDescriptor = resolutionResult.getReceiverParameterDescriptor();
recordThisOrSuperCallInTraceAndCallExtension(context, receiverParameterDescriptor, expression);
@@ -57,9 +57,9 @@ public class LabelResolver {
@Nullable
private Name getLabelNameIfAny(@NotNull PsiElement element) {
if (element instanceof JetLabeledExpression) {
String labelName = ((JetLabeledExpression) element).getLabelName();
Name labelName = ((JetLabeledExpression) element).getLabelNameAsName();
if (labelName != null) {
return Name.identifier(labelName);
return labelName;
}
}
if (element instanceof JetFunctionLiteralExpression) {
@@ -126,10 +126,9 @@ public class LabelResolver {
@NotNull ResolutionContext context
) {
JetSimpleNameExpression labelElement = expression.getTargetLabel();
String name = expression.getLabelName();
if (labelElement == null || name == null) return null;
Name labelName = expression.getLabelNameAsName();
if (labelElement == null || labelName == null) return null;
Name labelName = Name.identifier(name);
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
int size = declarationsByLabel.size();
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.name
import org.jetbrains.kotlin.renderer.DescriptorRenderer
public fun FqName.isSubpackageOf(packageName: FqName): Boolean {
return when {
this == packageName -> true
@@ -76,3 +78,5 @@ public fun isValidJavaFqName(qualifiedName: String?): Boolean {
return state != State.AFTER_DOT
}
public fun Name.renderName(): String = DescriptorRenderer.COMPACT.renderName(this)
@@ -16,9 +16,10 @@
package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
public fun JetFunctionLiteral.findLabelAndCall(): Pair<String?, JetCallExpression?> {
public fun JetFunctionLiteral.findLabelAndCall(): Pair<Name?, JetCallExpression?> {
val literalParent = (this.getParent() as JetFunctionLiteralExpression).getParent()
fun JetValueArgument.callExpression(): JetCallExpression? {
@@ -29,12 +30,12 @@ public fun JetFunctionLiteral.findLabelAndCall(): Pair<String?, JetCallExpressio
when (literalParent) {
is JetLabeledExpression -> {
val callExpression = (literalParent.getParent() as? JetValueArgument)?.callExpression()
return Pair(literalParent.getLabelName(), callExpression)
return Pair(literalParent.getLabelNameAsName(), callExpression)
}
is JetValueArgument -> {
val callExpression = literalParent.callExpression()
val label = (callExpression?.getCalleeExpression() as? JetSimpleNameExpression)?.getReferencedName()
val label = (callExpression?.getCalleeExpression() as? JetSimpleNameExpression)?.getReferencedNameAsName()
return Pair(label, callExpression)
}
@@ -20,6 +20,8 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.renderName
import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.psi.JetFunctionLiteral
import org.jetbrains.kotlin.psi.JetPsiFactory
@@ -58,7 +60,7 @@ public fun JetScope.getImplicitReceiversWithInstanceToExpression(): Map<Receiver
for ((index, receiver) in receivers.withIndex()) {
val owner = receiver.getContainingDeclaration()
val (expressionText, isImmediateThis) = if (owner in outerDeclarationsWithInstance) {
val thisWithLabel = thisQualifierName(receiver)?.let { "this@$it" }
val thisWithLabel = thisQualifierName(receiver)?.let { "this@${it.renderName()}" }
if (index == 0)
(thisWithLabel ?: "this") to true
else
@@ -83,12 +85,10 @@ public fun JetScope.getImplicitReceiversWithInstanceToExpression(): Map<Receiver
return result
}
private fun thisQualifierName(receiver: ReceiverParameterDescriptor): String? {
private fun thisQualifierName(receiver: ReceiverParameterDescriptor): Name? {
val descriptor = receiver.getContainingDeclaration()
val name = descriptor.getName()
if (!name.isSpecial()) {
return name.asString()
}
if (!name.isSpecial()) return name
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? JetFunctionLiteral
return functionLiteral?.findLabelAndCall()?.first
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.idea.util.FuzzyType
import org.jetbrains.kotlin.idea.util.findLabelAndCall
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstanceToExpression
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.renderName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.renderer.DescriptorRenderer
@@ -209,7 +210,7 @@ fun thisExpressionItems(bindingContext: BindingContext, position: JetExpression,
val thisType = receiver.getType()
val fuzzyType = FuzzyType(thisType, listOf())
fun createLookupElement() = createKeywordWithLabelElement("this", expression.getLabelName())
fun createLookupElement() = createKeywordWithLabelElement("this", expression.getLabelNameAsName())
.withTypeText(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(thisType))
result.add(ThisItemInfo(::createLookupElement, fuzzyType))
@@ -249,7 +250,7 @@ private fun returnsUnit(declaration: JetDeclarationWithBody, bindingContext: Bin
return KotlinBuiltIns.isUnit(returnType)
}
private fun createKeywordWithLabelElement(keyword: String, label: String?, addSpace: Boolean): LookupElement {
private fun createKeywordWithLabelElement(keyword: String, label: Name?, addSpace: Boolean): LookupElement {
val element = createKeywordWithLabelElement(keyword, label)
return if (addSpace) {
object: LookupElementDecorator<LookupElement>(element) {
@@ -263,12 +264,13 @@ private fun createKeywordWithLabelElement(keyword: String, label: String?, addSp
}
}
private fun createKeywordWithLabelElement(keyword: String, label: String?): LookupElementBuilder {
var element = LookupElementBuilder.create(KeywordLookupObject, if (label == null) keyword else "$keyword@$label")
private fun createKeywordWithLabelElement(keyword: String, label: Name?): LookupElementBuilder {
val labelInCode = label?.renderName()
var element = LookupElementBuilder.create(KeywordLookupObject, if (label == null) keyword else "$keyword@$labelInCode")
element = element.withPresentableText(keyword)
element = element.withBoldness(true)
if (label != null) {
element = element.withTailText("@$label", false)
element = element.withTailText("@$labelInCode", false)
}
return element
}
@@ -284,7 +286,7 @@ fun breakOrContinueExpressionItems(position: JetElement, breakOrContinue: String
result.add(createKeywordWithLabelElement(breakOrContinue, null))
}
val label = (parent.getParent() as? JetLabeledExpression)?.getLabelName()
val label = (parent.getParent() as? JetLabeledExpression)?.getLabelNameAsName()
if (label != null) {
result.add(createKeywordWithLabelElement(breakOrContinue, label))
}
@@ -4,5 +4,5 @@ class `this` {
}
}
// ELEMENT: "this@this"
// ELEMENT: "this@`this`"
@@ -1,8 +1,8 @@
class `this` {
fun String.foo(){
val foo: `this` = this@this<caret>
val foo: `this` = this@`this`<caret>
}
}
// ELEMENT: "this@this"
// ELEMENT: "this@`this`"
@@ -9,4 +9,4 @@ fun foo(){
})
}
// ELEMENT: this@fun
// ELEMENT: this@`fun`
@@ -4,9 +4,9 @@ fun bar(handler: Int.() -> Unit){}
fun foo(){
`fun`({
bar({
val s: String = this@fun<caret>
val s: String = this@`fun`<caret>
})
})
}
// ELEMENT: this@fun
// ELEMENT: this@`fun`
@@ -0,0 +1,14 @@
fun foo() {
`fun` {
`val`({ ret<caret> })
}
}
inline fun `fun`(handler: () -> Unit){}
inline fun `val`(handler: () -> Unit){}
// INVOCATION_COUNT: 1
// EXIST: { lookupString: "return", itemText: "return", tailText: null, attributes: "bold" }
// EXIST: { lookupString: "return@`fun`", itemText: "return", tailText: "@`fun`", attributes: "bold" }
// EXIST: { lookupString: "return@`val`", itemText: "return", tailText: "@`val`", attributes: "bold" }
// NOTHING_ELSE: true
@@ -401,6 +401,12 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName);
}
@TestMetadata("ReturnKeywordName.kt")
public void testReturnKeywordName() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/ReturnKeywordName.kt");
doTest(fileName);
}
@TestMetadata("This.kt")
public void testThis() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/This.kt");