Create From Usage: Do not generate type for local variables, but add dummy initializer instead
#KT-6705 Fixed
This commit is contained in:
Generated
+1
@@ -5,6 +5,7 @@
|
||||
<excludeFromCompile>
|
||||
<directory url="file://$PROJECT_DIR$/core/reflection" includeSubdirectories="true" />
|
||||
<directory url="file://$PROJECT_DIR$/core/reflection.jvm" includeSubdirectories="true" />
|
||||
<directory url="file://$PROJECT_DIR$/core/reflection.stub.jvm" includeSubdirectories="true" />
|
||||
</excludeFromCompile>
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
|
||||
@@ -182,6 +182,7 @@ public class CodeInsightUtils {
|
||||
return element;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String defaultInitializer(JetType type) {
|
||||
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
|
||||
if (type.isMarkedNullable()) {
|
||||
@@ -203,6 +204,12 @@ public class CodeInsightUtils {
|
||||
else if (type.equals(builtIns.getBooleanType())) {
|
||||
return "false";
|
||||
}
|
||||
else if (type.equals(builtIns.getUnitType())) {
|
||||
return "Unit";
|
||||
}
|
||||
else if (type.equals(builtIns.getStringType())) {
|
||||
return "\"\"";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
+12
-4
@@ -79,6 +79,7 @@ import org.jetbrains.kotlin.idea.refactoring.*
|
||||
import org.jetbrains.kotlin.idea.util.*
|
||||
import com.intellij.openapi.ui.*
|
||||
import com.intellij.codeInsight.template.impl.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.util.application.*
|
||||
|
||||
private val TYPE_PARAMETER_LIST_VARIABLE_NAME = "typeParameterList"
|
||||
@@ -324,7 +325,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
returnTypeCandidate?.theType?.isUnit() ?: false
|
||||
CallableKind.CONSTRUCTOR ->
|
||||
callableInfo.returnTypeInfo == TypeInfo.Empty || returnTypeCandidate?.theType?.isAny() ?: false
|
||||
CallableKind.PROPERTY -> false
|
||||
CallableKind.PROPERTY -> containingElement is JetBlockExpression
|
||||
}
|
||||
|
||||
// figure out type parameter renames to avoid conflicts
|
||||
@@ -883,6 +884,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
|
||||
private fun setupEditor(declaration: JetNamedDeclaration) {
|
||||
val caretModel = containingFileEditor.getCaretModel()
|
||||
val selectionModel = containingFileEditor.getSelectionModel()
|
||||
|
||||
caretModel.moveToOffset(declaration.getNameIdentifier().getTextRange().getEndOffset())
|
||||
|
||||
@@ -892,7 +894,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
val startOffset = from.getTextRange().getStartOffset()
|
||||
val endOffset = to.getTextRange().getEndOffset()
|
||||
caretModel.moveToOffset(endOffset)
|
||||
containingFileEditor.getSelectionModel().setSelection(startOffset, endOffset)
|
||||
selectionModel.setSelection(startOffset, endOffset)
|
||||
}
|
||||
|
||||
when (declaration) {
|
||||
@@ -903,9 +905,15 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
caretModel.moveToOffset(declaration.getTextRange().getStartOffset())
|
||||
}
|
||||
is JetProperty -> {
|
||||
if (!declaration.hasInitializer()) {
|
||||
caretModel.moveToOffset(declaration.getTextRange().getEndOffset())
|
||||
if (!declaration.hasInitializer() && containingElement is JetBlockExpression) {
|
||||
val defaultValueType = typeCandidates[callableInfo.returnTypeInfo].firstOrNull()?.theType
|
||||
?: KotlinBuiltIns.getInstance().getAnyType()
|
||||
val defaultValue = CodeInsightUtils.defaultInitializer(defaultValueType) ?: "null"
|
||||
val initializer = declaration.setInitializer(JetPsiFactory(declaration).createExpression(defaultValue))!!
|
||||
val range = initializer.getTextRange()
|
||||
selectionModel.setSelection(range.getStartOffset(), range.getEndOffset())
|
||||
}
|
||||
caretModel.moveToOffset(declaration.getTextRange().getEndOffset())
|
||||
}
|
||||
}
|
||||
containingFileEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE)
|
||||
|
||||
+38
-39
@@ -16,62 +16,61 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable
|
||||
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.CreateFromUsageFixBase
|
||||
import org.jetbrains.kotlin.idea.JetBundle
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import org.jetbrains.kotlin.idea.quickfix.QuickFixUtil
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElement
|
||||
import org.jetbrains.kotlin.psi.JetBlockExpression
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallableBuilderConfiguration
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.createBuilder
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallablePlacement
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.psi.JetElement
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.JetBundle
|
||||
import org.jetbrains.kotlin.idea.intentions.ConvertToBlockBodyAction
|
||||
import org.jetbrains.kotlin.psi.JetDeclarationWithBody
|
||||
import org.jetbrains.kotlin.idea.refactoring.getExtractionContainers
|
||||
import org.jetbrains.kotlin.psi.JetClassBody
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.PropertyInfo
|
||||
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
|
||||
import org.jetbrains.kotlin.idea.quickfix.QuickFixUtil
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.CreateFromUsageFixBase
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.getExpressionForTypeGuess
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
import java.util.Collections
|
||||
|
||||
object CreateLocalVariableActionFactory: JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val refExpr = QuickFixUtil.getParentElementOfType(diagnostic, javaClass<JetSimpleNameExpression>()) ?: return null
|
||||
if (refExpr.getQualifiedElement() != refExpr) return null
|
||||
|
||||
val propertyName = refExpr.getReferencedName()
|
||||
|
||||
val container = refExpr.parents(false)
|
||||
.filter { it is JetBlockExpression || it is JetDeclarationWithBody }
|
||||
.firstOrNull() as? JetElement ?: return null
|
||||
|
||||
val assignment = refExpr.getAssignmentByLHS()
|
||||
val varExpected = assignment != null
|
||||
val typeInfo = TypeInfo(
|
||||
refExpr.getExpressionForTypeGuess(),
|
||||
if (varExpected) Variance.INVARIANT else Variance.OUT_VARIANCE
|
||||
)
|
||||
val containers = refExpr.getExtractionContainers().filterNot { it is JetClassBody || it is JetFile }
|
||||
val propertyInfo = PropertyInfo(refExpr.getReferencedName(), TypeInfo.Empty, typeInfo, varExpected, containers)
|
||||
|
||||
return object: CreateFromUsageFixBase(refExpr) {
|
||||
override fun getText(): String = JetBundle.message("create.local.variable.from.usage", propertyInfo.name)
|
||||
override fun getText(): String = JetBundle.message("create.local.variable.from.usage", propertyName)
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: JetFile?) {
|
||||
with (CallableBuilderConfiguration(propertyInfo.singletonOrEmptyList(), assignment ?: refExpr, file!!, editor!!).createBuilder()) {
|
||||
val actualContainer = when (container) {
|
||||
is JetBlockExpression -> container
|
||||
else -> ConvertToBlockBodyAction.convert(container as JetDeclarationWithBody).getBodyExpression()!!
|
||||
}
|
||||
override fun invoke(project: Project, editor: Editor, file: JetFile) {
|
||||
val assignment = refExpr.getAssignmentByLHS()
|
||||
val varExpected = assignment != null
|
||||
var originalElement = assignment ?: refExpr
|
||||
|
||||
val actualContainer = when (container) {
|
||||
is JetBlockExpression -> container
|
||||
else -> ConvertToBlockBodyAction.convert(container as JetDeclarationWithBody).getBodyExpression()!!
|
||||
} as JetBlockExpression
|
||||
|
||||
if (actualContainer != container) {
|
||||
val bodyExpression = actualContainer.getStatements().first() as JetExpression
|
||||
originalElement = (bodyExpression as? JetReturnExpression)?.getReturnedExpression() ?: bodyExpression
|
||||
}
|
||||
|
||||
val typeInfo = TypeInfo(
|
||||
originalElement.getExpressionForTypeGuess(),
|
||||
if (varExpected) Variance.INVARIANT else Variance.OUT_VARIANCE
|
||||
)
|
||||
val propertyInfo = PropertyInfo(propertyName, TypeInfo.Empty, typeInfo, varExpected, Collections.singletonList(actualContainer))
|
||||
|
||||
with (CallableBuilderConfiguration(propertyInfo.singletonOrEmptyList(), originalElement, file, editor).createBuilder()) {
|
||||
placement = CallablePlacement.NoReceiver(actualContainer)
|
||||
CommandProcessor.getInstance().executeCommand(project, { build() }, getText(), null)
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fun foo() {
|
||||
var a: String
|
||||
var a: String = ""
|
||||
if () {
|
||||
a = "aaa"
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fun foo() {
|
||||
var a: String
|
||||
var a: String = ""
|
||||
if () {
|
||||
a = "aaa"
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
class A {
|
||||
val t: Int get() {
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
return foo
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
class A {
|
||||
val t: Int get() {
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
return foo
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(): Int {
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
return foo
|
||||
}
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(): Int {
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
return foo
|
||||
}
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int) {
|
||||
val f: () -> Int = {
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
foo
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int) {
|
||||
val f: (Int, Int) -> Int = { (a, b) ->
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
foo
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int) {
|
||||
val f: () -> Int = {
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
foo
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int) {
|
||||
val f: (Int, Int) -> Int = { (a, b) ->
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
foo
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int): Int {
|
||||
return when (n) {
|
||||
1 -> {
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
foo
|
||||
}
|
||||
else -> {
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
package foo
|
||||
|
||||
fun test(): Int {
|
||||
val foo: Int
|
||||
val foo = 0
|
||||
return foo
|
||||
}
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(): Int? {
|
||||
val foo: Int?
|
||||
val foo = null
|
||||
return foo
|
||||
}
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test() {
|
||||
val foo: Unit
|
||||
val foo = Unit
|
||||
val u: Unit = foo
|
||||
}
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
class A {
|
||||
val t: Int get() {
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
class A {
|
||||
val t: Int get() = <caret>foo
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(): Int {
|
||||
return <caret>foo
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(): Int = <caret>foo
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int) {
|
||||
val f: () -> Int = { <caret>foo }
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int) {
|
||||
val f: (Int, Int) -> Int = { (a, b) -> <caret>foo }
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int) {
|
||||
val f: () -> Int = {
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int) {
|
||||
val f: (Int, Int) -> Int = { (a, b) ->
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(n: Int): Int {
|
||||
return when (n) {
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
package foo
|
||||
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test(): Int? {
|
||||
return <caret>foo
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// "Create local variable 'foo'" "true"
|
||||
// ACTION: Create parameter 'foo'
|
||||
// ERROR: Variable 'foo' must be initialized
|
||||
|
||||
fun test() {
|
||||
val u: Unit = <caret>foo
|
||||
|
||||
Reference in New Issue
Block a user