KT-5874 Support code completion of label names after "continue@" and "break@"
#KT-5874 Fixed
This commit is contained in:
@@ -234,7 +234,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
val ampIndex = prefix.indexOf("@")
|
val ampIndex = prefix.indexOf("@")
|
||||||
val keywordsPrefix = if (ampIndex < 0) prefix else prefix.substring(0, ampIndex) // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc
|
val keywordsPrefix = if (ampIndex < 0) prefix else prefix.substring(0, ampIndex) // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc
|
||||||
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
|
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
|
||||||
when (lookupElement.getLookupString()) {
|
val keyword = lookupElement.getLookupString()
|
||||||
|
when (keyword) {
|
||||||
// if "this" is parsed correctly in the current context - insert it and all this@xxx items
|
// if "this" is parsed correctly in the current context - insert it and all this@xxx items
|
||||||
"this" -> {
|
"this" -> {
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
@@ -249,6 +250,12 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"break", "continue" -> {
|
||||||
|
if (expression != null) {
|
||||||
|
collector.addElements(breakOrContinueExpressionItems(expression, keyword))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else -> collector.addElement(lookupElement)
|
else -> collector.addElement(lookupElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor
|
|||||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
|
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||||
import org.jetbrains.jet.plugin.completion.handlers.WithTailInsertHandler
|
import org.jetbrains.jet.plugin.completion.handlers.WithTailInsertHandler
|
||||||
|
import org.jetbrains.jet.lang.psi.JetLoopExpression
|
||||||
|
|
||||||
enum class ItemPriority {
|
enum class ItemPriority {
|
||||||
MULTIPLE_ARGUMENTS_ITEM
|
MULTIPLE_ARGUMENTS_ITEM
|
||||||
@@ -333,3 +334,25 @@ private fun createKeywordWithLabelElement(keyword: String, label: String?): Look
|
|||||||
}
|
}
|
||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun breakOrContinueExpressionItems(position: JetElement, breakOrContinue: String): Collection<LookupElement> {
|
||||||
|
val result = ArrayList<LookupElement>()
|
||||||
|
for (parent in position.parents()) {
|
||||||
|
when (parent) {
|
||||||
|
is JetLoopExpression -> {
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
result.add(createKeywordWithLabelElement(breakOrContinue, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
val label = (parent.getParent() as? JetLabeledExpression)?.getLabelName()
|
||||||
|
if (label != null) {
|
||||||
|
result.add(createKeywordWithLabelElement(breakOrContinue, label))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is JetDeclarationWithBody -> break //TODO: support non-local break's&continue's when they are supported by compiler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
fun t() {
|
fun t() {
|
||||||
brea<caret>
|
while (true) {
|
||||||
|
brea<caret>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
fun t() {
|
fun t() {
|
||||||
break<caret>
|
while (true) {
|
||||||
|
break<caret>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
fun foo() {
|
||||||
|
@myFor
|
||||||
|
for (i in 1..10) {
|
||||||
|
@myWhile
|
||||||
|
while (x()) {
|
||||||
|
@myDo
|
||||||
|
do {
|
||||||
|
<caret>
|
||||||
|
} while (y())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "break", itemText: "break", tailText: null, attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "continue", itemText: "continue", tailText: null, attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "break@myDo", itemText: "break", tailText: "@myDo", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "continue@myDo", itemText: "continue", tailText: "@myDo", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "break@myWhile", itemText: "break", tailText: "@myWhile", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "continue@myWhile", itemText: "continue", tailText: "@myWhile", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "break@myFor", itemText: "break", tailText: "@myFor", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "continue@myFor", itemText: "continue", tailText: "@myFor", attributes: "bold" }
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
fun foo() {
|
||||||
|
@myFor
|
||||||
|
for (i in 1..10) {
|
||||||
|
@myWhile
|
||||||
|
while (x()) {
|
||||||
|
@myDo
|
||||||
|
do {
|
||||||
|
break@<caret>
|
||||||
|
} while (y())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "break@myDo", itemText: "break", tailText: "@myDo", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "break@myWhile", itemText: "break", tailText: "@myWhile", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "break@myFor", itemText: "break", tailText: "@myFor", attributes: "bold" }
|
||||||
|
// NUMBER: 3
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
fun foo() {
|
||||||
|
@myFor
|
||||||
|
for (i in 1..10) {
|
||||||
|
@myWhile
|
||||||
|
while (x()) {
|
||||||
|
@myDo
|
||||||
|
do {
|
||||||
|
continue@<caret>
|
||||||
|
} while (y())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "continue@myDo", itemText: "continue", tailText: "@myDo", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "continue@myWhile", itemText: "continue", tailText: "@myWhile", attributes: "bold" }
|
||||||
|
// EXIST: { lookupString: "continue@myFor", itemText: "continue", tailText: "@myFor", attributes: "bold" }
|
||||||
|
// NUMBER: 3
|
||||||
@@ -5,8 +5,6 @@ fun foo(p: Int) {
|
|||||||
z()
|
z()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: break
|
|
||||||
// EXIST: continue
|
|
||||||
// EXIST: do
|
// EXIST: do
|
||||||
// EXIST: false
|
// EXIST: false
|
||||||
// EXIST: for
|
// EXIST: for
|
||||||
@@ -21,4 +19,4 @@ fun foo(p: Int) {
|
|||||||
// EXIST: try
|
// EXIST: try
|
||||||
// EXIST: when
|
// EXIST: when
|
||||||
// EXIST: while
|
// EXIST: while
|
||||||
// NUMBER: 16
|
// NUMBER: 14
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ fun foo() {
|
|||||||
<caret>
|
<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: break
|
|
||||||
// EXIST: class
|
// EXIST: class
|
||||||
// EXIST: continue
|
|
||||||
// EXIST: do
|
// EXIST: do
|
||||||
// EXIST: false
|
// EXIST: false
|
||||||
// EXIST: for
|
// EXIST: for
|
||||||
@@ -23,4 +21,4 @@ fun foo() {
|
|||||||
// EXIST: var
|
// EXIST: var
|
||||||
// EXIST: when
|
// EXIST: when
|
||||||
// EXIST: while
|
// EXIST: while
|
||||||
// NUMBER: 21
|
// NUMBER: 19
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
fun foo() = <caret>
|
fun foo() = <caret>
|
||||||
|
|
||||||
// EXIST: break
|
|
||||||
// EXIST: continue
|
|
||||||
// EXIST: do
|
// EXIST: do
|
||||||
// EXIST: false
|
// EXIST: false
|
||||||
// EXIST: for
|
// EXIST: for
|
||||||
@@ -15,4 +13,4 @@ fun foo() = <caret>
|
|||||||
// EXIST: try
|
// EXIST: try
|
||||||
// EXIST: when
|
// EXIST: when
|
||||||
// EXIST: while
|
// EXIST: while
|
||||||
// NUMBER: 15
|
// NUMBER: 13
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
val prop: Int
|
val prop: Int
|
||||||
get() = <caret>
|
get() = <caret>
|
||||||
|
|
||||||
// EXIST: break
|
|
||||||
// EXIST: continue
|
|
||||||
// EXIST: do
|
// EXIST: do
|
||||||
// EXIST: false
|
// EXIST: false
|
||||||
// EXIST: for
|
// EXIST: for
|
||||||
@@ -16,4 +14,4 @@ val prop: Int
|
|||||||
// EXIST: try
|
// EXIST: try
|
||||||
// EXIST: when
|
// EXIST: when
|
||||||
// EXIST: while
|
// EXIST: while
|
||||||
// NUMBER: 15
|
// NUMBER: 13
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
fun foo(p: Int = <caret>)
|
fun foo(p: Int = <caret>)
|
||||||
|
|
||||||
// EXIST: break
|
|
||||||
// EXIST: continue
|
|
||||||
// EXIST: do
|
// EXIST: do
|
||||||
// EXIST: false
|
// EXIST: false
|
||||||
// EXIST: for
|
// EXIST: for
|
||||||
@@ -16,4 +14,4 @@ fun foo(p: Int = <caret>)
|
|||||||
// EXIST: try
|
// EXIST: try
|
||||||
// EXIST: when
|
// EXIST: when
|
||||||
// EXIST: while
|
// EXIST: while
|
||||||
// NUMBER: 16
|
// NUMBER: 14
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
var a : Int = <caret>
|
var a : Int = <caret>
|
||||||
|
|
||||||
// EXIST: break
|
|
||||||
// EXIST: continue
|
|
||||||
// EXIST: do
|
// EXIST: do
|
||||||
// EXIST: false
|
// EXIST: false
|
||||||
// EXIST: for
|
// EXIST: for
|
||||||
@@ -15,4 +13,4 @@ var a : Int = <caret>
|
|||||||
// EXIST: try
|
// EXIST: try
|
||||||
// EXIST: when
|
// EXIST: when
|
||||||
// EXIST: while
|
// EXIST: while
|
||||||
// NUMBER: 15
|
// NUMBER: 13
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun foo() {
|
||||||
|
@myFor
|
||||||
|
for (i in 1..10) {
|
||||||
|
while (x()) {
|
||||||
|
fun localFun(a: Int) {
|
||||||
|
if (a > 0) {
|
||||||
|
br<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NUMBER: 0
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
fun foo() {
|
||||||
|
@myFor
|
||||||
|
for (i in 1..10) {
|
||||||
|
while (x()) {
|
||||||
|
"abc".filter {
|
||||||
|
br<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NUMBER: 0
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun foo() {
|
||||||
|
@myFor
|
||||||
|
for (i in 1..10) {
|
||||||
|
while (x()) {
|
||||||
|
fun localFun(a: Int) {
|
||||||
|
if (a > 0) {
|
||||||
|
con<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NUMBER: 0
|
||||||
@@ -8,8 +8,10 @@ class Test(val br2 = 12) {
|
|||||||
fun brf() = 112
|
fun brf() = 112
|
||||||
|
|
||||||
fun test(br4: Int) {
|
fun test(br4: Int) {
|
||||||
val br5 = 14
|
while (true) {
|
||||||
br<caret>
|
val br5 = 14
|
||||||
|
br<caret>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.jetbrains.jet.completion;
|
|||||||
import com.intellij.testFramework.TestDataPath;
|
import com.intellij.testFramework.TestDataPath;
|
||||||
import org.jetbrains.jet.JUnit3RunnerWithInners;
|
import org.jetbrains.jet.JUnit3RunnerWithInners;
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
import org.jetbrains.jet.test.InnerTestClasses;
|
|
||||||
import org.jetbrains.jet.test.TestMetadata;
|
import org.jetbrains.jet.test.TestMetadata;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@@ -78,12 +77,30 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/completion/keywords"), Pattern.compile("^(.+)\\.kt$"), false);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/completion/keywords"), Pattern.compile("^(.+)\\.kt$"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("BreakContinue.kt")
|
||||||
|
public void testBreakContinue() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/BreakContinue.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("BreakWithLabel.kt")
|
||||||
|
public void testBreakWithLabel() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/BreakWithLabel.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("CommaExpected.kt")
|
@TestMetadata("CommaExpected.kt")
|
||||||
public void testCommaExpected() throws Exception {
|
public void testCommaExpected() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/CommaExpected.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/CommaExpected.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ContinueWithLabel.kt")
|
||||||
|
public void testContinueWithLabel() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/ContinueWithLabel.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("GlobalPropertyAccessors.kt")
|
@TestMetadata("GlobalPropertyAccessors.kt")
|
||||||
public void testGlobalPropertyAccessors() throws Exception {
|
public void testGlobalPropertyAccessors() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/GlobalPropertyAccessors.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/GlobalPropertyAccessors.kt");
|
||||||
@@ -240,12 +257,30 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NoBreak1.kt")
|
||||||
|
public void testNoBreak1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/NoBreak1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NoBreak2.kt")
|
||||||
|
public void testNoBreak2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/NoBreak2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("NoCompletionForCapitalPrefix.kt")
|
@TestMetadata("NoCompletionForCapitalPrefix.kt")
|
||||||
public void testNoCompletionForCapitalPrefix() throws Exception {
|
public void testNoCompletionForCapitalPrefix() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/NoCompletionForCapitalPrefix.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/NoCompletionForCapitalPrefix.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NoContinue.kt")
|
||||||
|
public void testNoContinue() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/NoContinue.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("NoFinalInParameterList.kt")
|
@TestMetadata("NoFinalInParameterList.kt")
|
||||||
public void testNoFinalInParameterList() throws Exception {
|
public void testNoFinalInParameterList() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/NoFinalInParameterList.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/keywords/NoFinalInParameterList.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user