KT-11957 No "catch" and "finally" keywords in completion

#KT-11957 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-04-18 22:42:10 +03:00
parent c7a96401da
commit 022075995b
10 changed files with 153 additions and 20 deletions
@@ -64,9 +64,8 @@ object KeywordCompletion {
WHILE_KEYWORD to "fun foo() { while(caret)",
FOR_KEYWORD to "fun foo() { for(caret)",
TRY_KEYWORD to "fun foo() { try {\ncaret\n}",
/* TODO!
CATCH_KEYWORD to "fun foo() { try {} catch (<caret>)",
*/
CATCH_KEYWORD to "fun foo() { try {} catch (caret)",
FINALLY_KEYWORD to "fun foo() { try {\n}\nfinally{\ncaret\n}",
DO_KEYWORD to "fun foo() { do {\ncaret\n}",
INIT_KEYWORD to "class C { init {\ncaret\n}",
CONSTRUCTOR_KEYWORD to "class C { constructor(caret)"
@@ -187,8 +186,15 @@ object KeywordCompletion {
while (parent != null) {
when (parent) {
is KtBlockExpression -> {
val prefixText = "fun foo() { "
var prefixText = "fun foo() { "
if (prevParent is KtExpression) {
val tryExpression = prevParent.prevSiblingOfSameType() as? KtTryExpression
if (tryExpression != null && tryExpression.finallyBlock == null) {
prefixText += when {
tryExpression.catchClauses.isEmpty() -> "try {}\n"
else -> "try {} catch (e: E) {}\n"
}
}
return buildFilterWithContext(prefixText, prevParent, position)
}
else {
@@ -100,10 +100,8 @@ fun createKeywordConstructLookupElement(
}
val indent = detectIndent(newFileText, keywordOffset)
if (indent != null) {
tailBeforeCaret = tailBeforeCaret.unindent(indent)
tailAfterCaret = tailAfterCaret.unindent(indent)
}
tailBeforeCaret = tailBeforeCaret.unindent(indent)
tailAfterCaret = tailAfterCaret.unindent(indent)
var lookupElementBuilder = LookupElementBuilder.create(KeywordLookupObject(), keyword)
.bold()
@@ -111,12 +109,10 @@ fun createKeywordConstructLookupElement(
if (insertionContext.completionChar == Lookup.NORMAL_SELECT_CHAR || insertionContext.completionChar == Lookup.REPLACE_SELECT_CHAR) {
val offset = insertionContext.tailOffset
val newIndent = detectIndent(insertionContext.document.charsSequence, offset - keyword.length)
var beforeCaret = tailBeforeCaret
var afterCaret = tailAfterCaret
if (newIndent != null) {
beforeCaret = beforeCaret.indentLinesAfterFirst(newIndent)
afterCaret = afterCaret.indentLinesAfterFirst(newIndent)
}
val beforeCaret = tailBeforeCaret.indentLinesAfterFirst(newIndent)
val afterCaret = tailAfterCaret.indentLinesAfterFirst(newIndent)
insertionContext.document.insertString(offset, beforeCaret + afterCaret)
insertionContext.editor.moveCaret(offset + beforeCaret.length)
}
@@ -127,19 +123,24 @@ fun createKeywordConstructLookupElement(
return lookupElementBuilder
}
private fun detectIndent(text: CharSequence, offset: Int): String? {
private fun detectIndent(text: CharSequence, offset: Int): String {
val reversedIndent = buildString {
var index = offset - 1
Loop@
while (index >= 0) {
val c = text[index]
when (c) {
' ', '\t' -> append(c)
'\r', '\n' -> break@Loop
else -> return null
if (c == '\n' || c == '\r') {
break
}
index--
}
index++
while (index < offset) {
val c = text[index]
if (!c.isWhitespace()) break
append(c)
index++
}
}
return reversedIndent.reversed()
}
@@ -0,0 +1,10 @@
fun t() {
while (true) {
try {
}
f<caret>
}
}
// ELEMENT: finally
@@ -0,0 +1,12 @@
fun t() {
while (true) {
try {
}
finally {
<caret>
}
}
}
// ELEMENT: finally
+13
View File
@@ -0,0 +1,13 @@
fun foo() {
try {
}
<caret>
}
// EXIST: catch
// EXIST: finally
// EXIST: false
// EXIST: null
// EXIST: true
// NOTHING_ELSE
+32
View File
@@ -0,0 +1,32 @@
fun foo() {
try {
}
catch(e: Exception) {
}
<caret>
}
// EXIST: catch
// EXIST: finally
// EXIST: class
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: super
// EXIST: throw
// EXIST: interface
// EXIST: true
// EXIST: try
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// EXIST: as
// NOTHING_ELSE
@@ -0,0 +1,29 @@
fun foo() {
try {
}
finally {
}
<caret>
}
// EXIST: class
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: super
// EXIST: throw
// EXIST: interface
// EXIST: true
// EXIST: try
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// NOTHING_ELSE
@@ -67,6 +67,24 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName);
}
@TestMetadata("AfterTry.kt")
public void testAfterTry() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/AfterTry.kt");
doTest(fileName);
}
@TestMetadata("AfterTryCatch.kt")
public void testAfterTryCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/AfterTryCatch.kt");
doTest(fileName);
}
@TestMetadata("AfterTryFinally.kt")
public void testAfterTryFinally() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/AfterTryFinally.kt");
doTest(fileName);
}
public void testAllFilesPresentInKeywords() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/keywords"), Pattern.compile("^(.+)\\.kt$"), false);
}
@@ -47,6 +47,12 @@ public class KeywordCompletionHandlerTestGenerated extends AbstractKeywordComple
doTest(fileName);
}
@TestMetadata("Catch.kt")
public void testCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/Catch.kt");
doTest(fileName);
}
@TestMetadata("CompanionObject.kt")
public void testCompanionObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/CompanionObject.kt");
@@ -71,6 +77,12 @@ public class KeywordCompletionHandlerTestGenerated extends AbstractKeywordComple
doTest(fileName);
}
@TestMetadata("Finally.kt")
public void testFinally() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/Finally.kt");
doTest(fileName);
}
@TestMetadata("For.kt")
public void testFor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/keywords/For.kt");