Surround with try/catch should generate more Kotlin-style code (KT-5435)

#KT-5435 Fixed
This commit is contained in:
shiraji
2016-10-09 12:10:45 +03:00
committed by Nikolay Krasko
parent c7c51a3d6b
commit 06dad5f45b
19 changed files with 97 additions and 57 deletions
@@ -50,17 +50,22 @@ fun move(container: PsiElement, statements: Array<PsiElement>, generateDefaultIn
val scope = LocalSearchScope(container) val scope = LocalSearchScope(container)
val lastStatementOffset = statements[statements.size - 1].textRange.endOffset val lastStatementOffset = statements[statements.size - 1].textRange.endOffset
for (statement in statements) { statements.forEachIndexed { i, statement ->
if (needToDeclareOut(statement, lastStatementOffset, scope)) { if (needToDeclareOut(statement, lastStatementOffset, scope)) {
val property = statement as? KtProperty val property = statement as? KtProperty
if (property?.initializer != null) { if (property?.initializer != null) {
var declaration = createVariableDeclaration(property, generateDefaultInitializers) if (i == statements.size - 1) {
declaration = container.addBefore(declaration, dummyFirstStatement) as KtProperty kotlinStyleDeclareOut(container, dummyFirstStatement, resultStatements, propertiesDeclarations, property)
propertiesDeclarations.add(declaration) } else {
container.addAfter(psiFactory.createNewLine(), declaration) declareOut(
container,
val assignment = createVariableAssignment(property) dummyFirstStatement,
resultStatements.add(property.replace(assignment)) generateDefaultInitializers,
resultStatements,
propertiesDeclarations,
property
)
}
} else { } else {
val newStatement = container.addBefore(statement, dummyFirstStatement) val newStatement = container.addBefore(statement, dummyFirstStatement)
container.addAfter(psiFactory.createNewLine(), newStatement) container.addAfter(psiFactory.createNewLine(), newStatement)
@@ -79,6 +84,38 @@ fun move(container: PsiElement, statements: Array<PsiElement>, generateDefaultIn
return PsiUtilCore.toPsiElementArray(resultStatements) return PsiUtilCore.toPsiElementArray(resultStatements)
} }
private fun kotlinStyleDeclareOut(
container: PsiElement,
dummyFirstStatement: PsiElement,
resultStatements: ArrayList<PsiElement>,
propertiesDeclarations: ArrayList<KtProperty>,
property: KtProperty
) {
val name = property.name ?: return
var declaration = KtPsiFactory(property).createProperty(name, property.typeReference?.text, property.isVar, null)
declaration = container.addBefore(declaration, dummyFirstStatement) as KtProperty
container.addAfter(KtPsiFactory(declaration).createEQ(), declaration)
propertiesDeclarations.add(declaration)
property.initializer?.let {
resultStatements.add(property.replace(it))
}
}
private fun declareOut(
container: PsiElement,
dummyFirstStatement: PsiElement,
generateDefaultInitializers: Boolean,
resultStatements: ArrayList<PsiElement>,
propertiesDeclarations: ArrayList<KtProperty>,
property: KtProperty
) {
var declaration = createVariableDeclaration(property, generateDefaultInitializers)
declaration = container.addBefore(declaration, dummyFirstStatement) as KtProperty
propertiesDeclarations.add(declaration)
val assignment = createVariableAssignment(property)
resultStatements.add(property.replace(assignment))
}
private fun createVariableAssignment(property: KtProperty): KtBinaryExpression { private fun createVariableAssignment(property: KtProperty): KtBinaryExpression {
val propertyName = property.name ?: error("Property should have a name " + property.text) val propertyName = property.name ?: error("Property should have a name " + property.text)
val assignment = KtPsiFactory(property).createExpression("$propertyName = x") as KtBinaryExpression val assignment = KtPsiFactory(property).createExpression("$propertyName = x") as KtBinaryExpression
@@ -105,11 +142,10 @@ private fun getPropertyType(property: KtProperty): KotlinType {
private fun createProperty(property: KtProperty, propertyType: KotlinType, initializer: String?): KtProperty { private fun createProperty(property: KtProperty, propertyType: KotlinType, initializer: String?): KtProperty {
val typeRef = property.typeReference val typeRef = property.typeReference
var typeString: String? = null val typeString = when {
if (typeRef != null) { typeRef != null -> typeRef.text
typeString = typeRef.text !propertyType.isError -> IdeDescriptorRenderers.SOURCE_CODE.renderType(propertyType)
} else if (!propertyType.isError) { else -> null
typeString = IdeDescriptorRenderers.SOURCE_CODE.renderType(propertyType)
} }
return KtPsiFactory(property).createProperty(property.name!!, typeString, property.isVar, initializer) return KtPsiFactory(property).createProperty(property.name!!, typeString, property.isVar, initializer)
@@ -1,9 +1,8 @@
fun foo() { fun foo() {
val a: String val a: String
val b: String val b = <selection>run</selection> {
<selection>run</selection> {
a = "aaa" a = "aaa"
b = "aaa" "aaa"
} }
a.charAt(1) a.charAt(1)
@@ -3,9 +3,9 @@ fun foo() {
fun test() {} fun test() {}
} }
val d: A val d: A =
if (<caret>) { if (<caret>) {
d = A() A()
} }
d.test() d.test()
@@ -1,9 +1,8 @@
fun foo() { fun foo() {
val a: String val a: String
val b: String val b = if (<caret>) {
if (<caret>) {
a = "aaa" a = "aaa"
b = a a
} }
a.charAt(1) a.charAt(1)
@@ -1,7 +1,6 @@
fun foo() { fun foo() {
val a: kotlin.test.Asserter? val a: kotlin.test.Asserter? = if (<caret>) {
if (<caret>) { null
a = null
} }
a?.charAt(1) a?.charAt(1)
@@ -3,9 +3,8 @@ package test
class A {} class A {}
fun foo() { fun foo() {
val a: A val a = if (<caret>) {
if (<caret>) { test.A()
a = test.A()
} }
a.hashCode() a.hashCode()
@@ -1,7 +1,6 @@
fun foo() { fun foo() {
val a: String val a: String = if () {
if () { "aaa"
a = "aaa"
} }
a.charAt(1) a.charAt(1)
@@ -1,7 +1,6 @@
fun foo() { fun foo() {
val a: String val a = if () {
if () { "aaa"
a = "aaa"
} }
a.charAt(1) a.charAt(1)
@@ -1,7 +1,6 @@
fun foo() { fun foo() {
var a: Boolean = false var a: Boolean = if (<caret>) {
if (<caret>) { true
a = true
} }
a = true a = true
} }
@@ -1,7 +1,6 @@
fun foo() { fun foo() {
var a: String? = null var a: String? = if (<caret>) {
if (<caret>) { "aaa"
a = "aaa"
} }
a = "bbb" a = "bbb"
} }
@@ -5,15 +5,14 @@ fun foo() {
var d: Long = 0 var d: Long = 0
var e: Short = 0 var e: Short = 0
var f: Double = 0.0 var f: Double = 0.0
var g: Float = 0.0f var g: Float = if () {
if () {
a = 1 a = 1
b = 1 b = 1
c = 1 c = 1
d = 1 d = 1
e = 1 e = 1
f = 1 f = 1
g = 1 1
} }
a = 2 a = 2
b = 2 b = 2
@@ -1,7 +1,6 @@
fun foo() { fun foo() {
var a: String = "" var a: String = if () {
if () { "aaa"
a = "aaa"
} }
a.charAt(1) a.charAt(1)
@@ -1,7 +1,6 @@
fun foo() { fun foo() {
var a: String = "" var a = if () {
if () { "aaa"
a = "aaa"
} }
a.charAt(1) a.charAt(1)
@@ -1,7 +1,6 @@
fun foo() { fun foo() {
val a: String? val a: String? = if (<caret>) {
if (<caret>) { "aaa"
a = "aaa"
} else { } else {
} }
a.toString() a.toString()
@@ -1,7 +1,6 @@
fun foo() { fun foo() {
var a: String? var a: String? = if (<caret>) {
if (<caret>) { "aaa"
a = "aaa"
} else { } else {
} }
a = "bbb" a = "bbb"
@@ -1,9 +1,8 @@
fun foo() { fun foo() {
val a: String val a: String
val b: String val b = try {
try {
a = "aaa" a = "aaa"
b = "aaa" "aaa"
} catch (e: <selection>Exception</selection>) { } catch (e: <selection>Exception</selection>) {
} }
@@ -0,0 +1,5 @@
fun foo() {
<selection>val a = "aaa"</selection>
a.charAt(1)
}
@@ -0,0 +1,8 @@
fun foo() {
val a = try {
"aaa"
} catch (e: <selection><caret>Exception</selection>) {
}
a.charAt(1)
}
@@ -587,6 +587,11 @@ public class SurroundWithTestGenerated extends AbstractSurroundWithTest {
runTest("idea/testData/codeInsight/surroundWith/tryCatch/moveDeclarationsOut.kt"); runTest("idea/testData/codeInsight/surroundWith/tryCatch/moveDeclarationsOut.kt");
} }
@TestMetadata("moveDeclarationsOutSingleStatement.kt")
public void testMoveDeclarationsOutSingleStatement() throws Exception {
runTest("idea/testData/codeInsight/surroundWith/tryCatch/moveDeclarationsOutSingleStatement.kt");
}
@TestMetadata("multiExpression.kt") @TestMetadata("multiExpression.kt")
public void testMultiExpression() throws Exception { public void testMultiExpression() throws Exception {
runTest("idea/testData/codeInsight/surroundWith/tryCatch/multiExpression.kt"); runTest("idea/testData/codeInsight/surroundWith/tryCatch/multiExpression.kt");