Implement a bunch of string based postfix templates

#KT-4710 Fixed
This commit is contained in:
Denis Zharkov
2016-07-12 16:13:00 +03:00
committed by Nikolay Krasko
parent 1b391123e6
commit 189705727f
28 changed files with 178 additions and 6 deletions
@@ -0,0 +1,3 @@
fun foo(x: Boolean) {
assert(x) { "" }
}
@@ -0,0 +1,3 @@
fun foo(x: Boolean) {
<spot>x</spot>$key
}
@@ -0,0 +1,5 @@
<html>
<body>
Creates assertion from boolean expression.
</body>
</html>
@@ -0,0 +1,3 @@
fun foo(x: Any) {
(x)
}
@@ -0,0 +1,3 @@
fun foo(x: Any) {
<spot>x</spot>$key
}
@@ -0,0 +1,5 @@
<html>
<body>
Parenthesizes expression.
</body>
</html>
@@ -0,0 +1,3 @@
fun foo(x: Any): Any {
return x
}
@@ -0,0 +1,3 @@
fun foo(x: Any): Any {
<spot>x</spot>$key
}
@@ -0,0 +1,5 @@
<html>
<body>
Creates return statement.
</body>
</html>
@@ -0,0 +1,3 @@
fun foo(x: Any) {
println(x)
}
@@ -0,0 +1,3 @@
fun foo(x: Any) {
<spot>x</spot>$key
}
@@ -0,0 +1,5 @@
<html>
<body>
Creates println() call.
</body>
</html>
@@ -0,0 +1,5 @@
fun foo(x: Boolean) {
while(x) {
}
}
@@ -0,0 +1,3 @@
fun foo(x: Boolean) {
<spot>x</spot>$key
}
@@ -0,0 +1,5 @@
<html>
<body>
Creates while statement from boolean expression.
</body>
</html>
@@ -46,7 +46,12 @@ class KtPostfixTemplateProvider : PostfixTemplateProvider {
KtIntroduceVariablePostfixTemplate("val"),
KtIntroduceVariablePostfixTemplate("var"),
KtForEachPostfixTemplate("for"),
KtForEachPostfixTemplate("iter")
KtForEachPostfixTemplate("iter"),
KtAssertPostfixTemplate,
KtParenthesizedPostfixTemplate,
KtSoutPostfixTemplate,
KtReturnPostfixTemplate,
KtWhilePostfixTemplate
)
override fun isTerminalSymbol(currentChar: Char) = currentChar == '.' || currentChar == '!'
@@ -19,28 +19,76 @@ package org.jetbrains.kotlin.idea.codeInsight.postfix
import com.intellij.codeInsight.template.Template
import com.intellij.codeInsight.template.impl.ConstantNode
import com.intellij.codeInsight.template.impl.MacroCallNode
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplateExpressionSelector
import com.intellij.codeInsight.template.postfix.templates.StringBasedPostfixTemplate
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.liveTemplates.macro.SuggestVariableNameMacro
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isBoolean
import org.jetbrains.kotlin.types.typeUtil.isIterator
import org.jetbrains.kotlin.util.OperatorNameConventions
internal abstract class ConstantStringBasedPostfixTemplate(
name: String,
desc: String,
private val template: String,
selector: PostfixTemplateExpressionSelector
) : StringBasedPostfixTemplate(name, desc, selector) {
override fun getTemplateString(element: PsiElement) = template
override fun getElementToRemove(expr: PsiElement?) = expr
}
internal class KtForEachPostfixTemplate(
name: String
) : StringBasedPostfixTemplate(name, "for (item in expr)", createExpressionSelector(statementsOnly = true, predicate = KotlinType::containsIteratorMethod)) {
override fun getTemplateString(element: PsiElement) = "for (\$name$ in \$expr$) {\n \$END$\n}"
) : ConstantStringBasedPostfixTemplate(
name,
"for (item in expr)",
"for (\$name$ in \$expr$) {\n \$END$\n}",
createExpressionSelector(statementsOnly = true, predicate = KotlinType::containsIteratorMethod)
) {
override fun setVariables(template: Template, element: PsiElement) {
val name = MacroCallNode(SuggestVariableNameMacro())
template.addVariable("name", name, ConstantNode("item"), true)
}
override fun getElementToRemove(expr: PsiElement?) = expr
}
private fun KotlinType.containsIteratorMethod() =
memberScope.getContributedFunctions(OperatorNameConventions.ITERATOR, NoLookupLocation.FROM_IDE).any {
it.returnType?.isIterator() ?: false && it.valueParameters.isEmpty()
}
internal object KtAssertPostfixTemplate : ConstantStringBasedPostfixTemplate(
"assert",
"assert(expr) { \"\" }",
"assert(\$expr$) { \"\$END$\" }",
createExpressionSelector(statementsOnly = false, predicate = KotlinType::isBoolean)
)
internal object KtParenthesizedPostfixTemplate : ConstantStringBasedPostfixTemplate(
"par", "(expr)",
"(\$expr$)\$END$",
createExpressionSelector(statementsOnly = false)
)
internal object KtSoutPostfixTemplate : ConstantStringBasedPostfixTemplate(
"sout",
"println(expr)",
"println(\$expr$)\$END$",
createExpressionSelector(statementsOnly = true)
)
internal object KtReturnPostfixTemplate : ConstantStringBasedPostfixTemplate(
"return",
"return expr",
"return \$expr$\$END$",
createExpressionSelector(statementsOnly = false)
)
internal object KtWhilePostfixTemplate : ConstantStringBasedPostfixTemplate(
"while",
"while (expr) {}",
"while (\$expr$) {\n\$END$\n}",
createExpressionSelector(statementsOnly = true, predicate = KotlinType::isBoolean)
)
+3
View File
@@ -0,0 +1,3 @@
fun foo(x: Boolean) {
x.assert<caret>
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(x: Boolean) {
assert(x) { "<caret>" }
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(x: Any) {
x.par<caret>
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(x: Any) {
(x)<caret>
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(x: Any): Any {
x.return<caret>
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(x: Any): Any {
return x
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(x: Any) {
x.sout<caret>
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(x: Any) {
println(x)<caret>
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(x: Boolean) {
x.while<caret>
}
+5
View File
@@ -0,0 +1,5 @@
fun foo(x: Boolean) {
while (x) {
<caret>
}
}
@@ -35,6 +35,12 @@ public class PostfixTemplateProviderTestGenerated extends AbstractPostfixTemplat
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/codeInsight/postfix"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("assert.kt")
public void testAssert() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/assert.kt");
doTest(fileName);
}
@TestMetadata("else.kt")
public void testElse() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/else.kt");
@@ -83,6 +89,24 @@ public class PostfixTemplateProviderTestGenerated extends AbstractPostfixTemplat
doTest(fileName);
}
@TestMetadata("par.kt")
public void testPar() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/par.kt");
doTest(fileName);
}
@TestMetadata("return.kt")
public void testReturn() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/return.kt");
doTest(fileName);
}
@TestMetadata("sout.kt")
public void testSout() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/sout.kt");
doTest(fileName);
}
@TestMetadata("try.kt")
public void testTry() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/try.kt");
@@ -106,4 +130,10 @@ public class PostfixTemplateProviderTestGenerated extends AbstractPostfixTemplat
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/when.kt");
doTest(fileName);
}
@TestMetadata("while.kt")
public void testWhile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/while.kt");
doTest(fileName);
}
}