Fixed keywords after 'this@' completion + fixed implementation of JetExpressionWithLabel.getLabelName()
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
+6
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user