Implement for/iter postfix templates

#KT-4710 In Progress
This commit is contained in:
Denis Zharkov
2016-07-11 16:03:46 +03:00
committed by Nikolay Krasko
parent b702886f0d
commit 1b391123e6
12 changed files with 90 additions and 1 deletions
@@ -60,6 +60,7 @@ fun KotlinType.isBoolean(): Boolean = KotlinBuiltIns.isBoolean(this)
fun KotlinType.isPrimitiveNumberType(): Boolean = KotlinBuiltIns.isPrimitiveType(this) && !isBoolean()
fun KotlinType.isBooleanOrNullableBoolean(): Boolean = KotlinBuiltIns.isBooleanOrNullableBoolean(this)
fun KotlinType.isThrowable(): Boolean = isConstructedFromClassWithGivenFqName(KotlinBuiltIns.FQ_NAMES.throwable) && !isMarkedNullable
fun KotlinType.isIterator(): Boolean = isConstructedFromClassWithGivenFqName(KotlinBuiltIns.FQ_NAMES.iterator) && !isMarkedNullable
fun KotlinType.isConstructedFromClassWithGivenFqName(fqName: FqName) =
(constructor.declarationDescriptor as? ClassDescriptor)?.fqNameUnsafe == fqName.toUnsafe()
@@ -0,0 +1,4 @@
fun bar() = 1
fun foo() {
val bar = bar()
}
@@ -0,0 +1,3 @@
fun foo(list: List<String>) {
<spot>list</spot>$key
}
@@ -0,0 +1,5 @@
<html>
<body>
Creates for statement from given iterable expression.
</body>
</html>
@@ -44,7 +44,9 @@ class KtPostfixTemplateProvider : PostfixTemplateProvider {
KtWhenExpressionPostfixTemplate,
KtTryPostfixTemplate,
KtIntroduceVariablePostfixTemplate("val"),
KtIntroduceVariablePostfixTemplate("var")
KtIntroduceVariablePostfixTemplate("var"),
KtForEachPostfixTemplate("for"),
KtForEachPostfixTemplate("iter")
)
override fun isTerminalSymbol(currentChar: Char) = currentChar == '.' || currentChar == '!'
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.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.isIterator
import org.jetbrains.kotlin.util.OperatorNameConventions
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}"
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()
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(list: List<String>) {
list.for<caret>
}
+5
View File
@@ -0,0 +1,5 @@
fun foo(list: List<String>) {
for (s in list) {
<caret>
}
}
+3
View File
@@ -0,0 +1,3 @@
fun foo(list: List<String>) {
list.iter<caret>
}
+5
View File
@@ -0,0 +1,5 @@
fun foo(list: List<String>) {
for (s in list) {
<caret>
}
}
@@ -41,12 +41,24 @@ public class PostfixTemplateProviderTestGenerated extends AbstractPostfixTemplat
doTest(fileName);
}
@TestMetadata("for.kt")
public void testFor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/for.kt");
doTest(fileName);
}
@TestMetadata("if.kt")
public void testIf() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/if.kt");
doTest(fileName);
}
@TestMetadata("iter.kt")
public void testIter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/iter.kt");
doTest(fileName);
}
@TestMetadata("notBoolean.kt")
public void testNotBoolean() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/notBoolean.kt");