Allow to convert nullable local / top to late-init since version 1.2

Enhancement for KT-12743
This commit is contained in:
Mikhail Glukhikh
2018-11-29 19:45:49 +03:00
parent 4cf266e99f
commit 4e1d8fcfd0
9 changed files with 36 additions and 10 deletions
@@ -7,10 +7,13 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.setType
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtNullableType
import org.jetbrains.kotlin.psi.KtProperty
@@ -27,7 +30,9 @@ class ConvertNullablePropertyToLateinitIntention : SelfTargetingIntention<KtProp
override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean {
if (element.hasModifier(KtTokens.LATEINIT_KEYWORD) || element.hasModifier(KtTokens.ABSTRACT_KEYWORD)) return false
if (!element.isVar) return false
if (element.isLocal || element.isTopLevel) return false
val languageVersionSettings = element.languageVersionSettings
if (!languageVersionSettings.supportsFeature(LanguageFeature.LateinitLocalVariables) && element.isLocal) return false
if (!languageVersionSettings.supportsFeature(LanguageFeature.LateinitTopLevelProperties) && element.isTopLevel) return false
if (element.getter?.hasBody() != null || element.setter?.hasBody() != null) return false
if (!element.initializer.isNullExpression()) return false
@@ -37,8 +42,8 @@ class ConvertNullablePropertyToLateinitIntention : SelfTargetingIntention<KtProp
val type = context[BindingContext.TYPE, typeReference]?.makeNotNullable() ?: return false
if (KotlinBuiltIns.isPrimitiveType(type) || type.isInlineClassType() || TypeUtils.isNullableType(type)) return false
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? PropertyDescriptor ?: return false
if (context[BindingContext.BACKING_FIELD_REQUIRED, descriptor] == false) return false
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? VariableDescriptor ?: return false
if (descriptor is PropertyDescriptor && context[BindingContext.BACKING_FIELD_REQUIRED, descriptor] == false) return false
if (descriptor.extensionReceiverParameter != null) return false
return true
@@ -1,4 +1,3 @@
// IS_APPLICABLE: false
fun test() {
<caret>var foo: String? = null
}
@@ -0,0 +1,3 @@
fun test() {
lateinit var foo: String
}
@@ -0,0 +1,5 @@
// IS_APPLICABLE: false
// LANGUAGE_VERSION: 1.1
fun test() {
<caret>var foo: String? = null
}
@@ -1,2 +1 @@
// IS_APPLICABLE: false
<caret>var foo: String? = null
@@ -0,0 +1 @@
lateinit var foo: String
@@ -0,0 +1,3 @@
// IS_APPLICABLE: false
// LANGUAGE_VERSION: 1.1
<caret>var foo: String? = null
@@ -33,9 +33,7 @@ import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.testFramework.PlatformTestUtil
import junit.framework.ComparisonFailure
import junit.framework.TestCase
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.*
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.InTextDirectivesUtils
@@ -106,6 +104,7 @@ abstract class AbstractIntentionTest : KotlinLightCodeInsightFixtureTestCase() {
val pathToFiles = mapOf(*(sourceFilePaths zip psiFiles).toTypedArray())
val fileText = FileUtil.loadFile(mainFile, true)
val configured = configureCompilerOptions(fileText, project, module)
ConfigLibraryUtil.configureLibrariesByDirective(myModule, PlatformTestUtil.getCommunityPath(), fileText)
@@ -124,9 +123,11 @@ abstract class AbstractIntentionTest : KotlinLightCodeInsightFixtureTestCase() {
if (file is KtFile && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// SKIP_ERRORS_AFTER")) {
DirectiveBasedActionUtils.checkForUnexpectedErrors(file as KtFile)
}
}
finally {
} finally {
ConfigLibraryUtil.unconfigureLibrariesByDirective(myModule, fileText)
if (configured) {
rollbackCompilerOptions(project, module)
}
}
}
@@ -5910,6 +5910,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/convertNullablePropertyToLateinit/local.kt");
}
@TestMetadata("localLegacy.kt")
public void testLocalLegacy() throws Exception {
runTest("idea/testData/intentions/convertNullablePropertyToLateinit/localLegacy.kt");
}
@TestMetadata("nonNullInitializer.kt")
public void testNonNullInitializer() throws Exception {
runTest("idea/testData/intentions/convertNullablePropertyToLateinit/nonNullInitializer.kt");
@@ -5940,6 +5945,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/convertNullablePropertyToLateinit/topLevel.kt");
}
@TestMetadata("topLevelLegacy.kt")
public void testTopLevelLegacy() throws Exception {
runTest("idea/testData/intentions/convertNullablePropertyToLateinit/topLevelLegacy.kt");
}
@TestMetadata("unsignedInt.kt")
public void testUnsignedInt() throws Exception {
runTest("idea/testData/intentions/convertNullablePropertyToLateinit/unsignedInt.kt");