Minor code improvements
This commit is contained in:
@@ -21,7 +21,6 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.util.IncorrectOperationException
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
@@ -40,9 +39,11 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
|||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.dataClassUtils.getComponentIndex
|
import org.jetbrains.kotlin.resolve.dataClassUtils.getComponentIndex
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinType) : KotlinQuickFixAction<KtFunction>(element) {
|
class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinType) : KotlinQuickFixAction<KtFunction>(element) {
|
||||||
@@ -63,9 +64,7 @@ class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinT
|
|||||||
return changeFunctionLiteralReturnTypeFix.text
|
return changeFunctionLiteralReturnTypeFix.text
|
||||||
}
|
}
|
||||||
|
|
||||||
var functionName = element.name
|
val functionName = element.fqName?.asString() ?: element.name
|
||||||
val fqName = element.fqName
|
|
||||||
if (fqName != null) functionName = fqName.asString()
|
|
||||||
|
|
||||||
if (KotlinBuiltIns.isUnit(type) && element.hasBlockBody()) {
|
if (KotlinBuiltIns.isUnit(type) && element.hasBlockBody()) {
|
||||||
return if (functionName == null)
|
return if (functionName == null)
|
||||||
@@ -73,6 +72,7 @@ class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinT
|
|||||||
else
|
else
|
||||||
KotlinBundle.message("remove.function.return.type", functionName)
|
KotlinBundle.message("remove.function.return.type", functionName)
|
||||||
}
|
}
|
||||||
|
|
||||||
val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
|
val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
|
||||||
return if (functionName == null)
|
return if (functionName == null)
|
||||||
KotlinBundle.message("change.no.name.function.return.type", renderedType)
|
KotlinBundle.message("change.no.name.function.return.type", renderedType)
|
||||||
@@ -80,9 +80,7 @@ class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinT
|
|||||||
KotlinBundle.message("change.function.return.type", functionName, renderedType)
|
KotlinBundle.message("change.function.return.type", functionName, renderedType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFamilyName(): String {
|
override fun getFamilyName() = KotlinBundle.message("change.type.family")
|
||||||
return KotlinBundle.message("change.type.family")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
||||||
return super.isAvailable(project, editor, file) &&
|
return super.isAvailable(project, editor, file) &&
|
||||||
@@ -90,17 +88,15 @@ class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinT
|
|||||||
element !is KtConstructor<*>
|
element !is KtConstructor<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IncorrectOperationException::class)
|
override operator fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||||
public override operator fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
|
||||||
if (changeFunctionLiteralReturnTypeFix != null) {
|
if (changeFunctionLiteralReturnTypeFix != null) {
|
||||||
changeFunctionLiteralReturnTypeFix.invoke(project, editor!!, file)
|
changeFunctionLiteralReturnTypeFix.invoke(project, editor!!, file)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!(KotlinBuiltIns.isUnit(type) && element.hasBlockBody())) {
|
if (!(type.isUnit() && element.hasBlockBody())) {
|
||||||
var newTypeRef: KtTypeReference? = KtPsiFactory(project).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
|
var newTypeRef = KtPsiFactory(project).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
|
||||||
newTypeRef = element.setTypeReference(newTypeRef)
|
newTypeRef = element.setTypeReference(newTypeRef)!!
|
||||||
assert(newTypeRef != null)
|
ShortenReferences.DEFAULT.process(newTypeRef)
|
||||||
ShortenReferences.DEFAULT.process(newTypeRef!!)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
element.typeReference = null
|
element.typeReference = null
|
||||||
@@ -121,15 +117,11 @@ class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinT
|
|||||||
return object : KotlinSingleIntentionActionFactory() {
|
return object : KotlinSingleIntentionActionFactory() {
|
||||||
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||||
val entry = getDestructuringDeclarationEntryThatTypeMismatchComponentFunction(diagnostic)
|
val entry = getDestructuringDeclarationEntryThatTypeMismatchComponentFunction(diagnostic)
|
||||||
val context = entry.analyze()
|
val context = entry.analyze(BodyResolveMode.PARTIAL)
|
||||||
val resolvedCall = context.get(BindingContext.COMPONENT_RESOLVED_CALL, entry) ?: return null
|
val resolvedCall = context.get(BindingContext.COMPONENT_RESOLVED_CALL, entry) ?: return null
|
||||||
val componentFunction = DescriptorToSourceUtils.descriptorToDeclaration(resolvedCall.candidateDescriptor) as KtFunction?
|
val componentFunction = DescriptorToSourceUtils.descriptorToDeclaration(resolvedCall.candidateDescriptor) as KtFunction? ?: return null
|
||||||
val expectedType = context.get(BindingContext.TYPE, entry.typeReference!!)
|
val expectedType = context[BindingContext.TYPE, entry.typeReference!!] ?: return null
|
||||||
if (componentFunction != null && expectedType != null) {
|
return ChangeFunctionReturnTypeFix(componentFunction, expectedType)
|
||||||
return ChangeFunctionReturnTypeFix(componentFunction, expectedType)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,16 +129,13 @@ class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinT
|
|||||||
fun createFactoryForHasNextFunctionTypeMismatch(): KotlinSingleIntentionActionFactory {
|
fun createFactoryForHasNextFunctionTypeMismatch(): KotlinSingleIntentionActionFactory {
|
||||||
return object : KotlinSingleIntentionActionFactory() {
|
return object : KotlinSingleIntentionActionFactory() {
|
||||||
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||||
val expression = QuickFixUtil.getParentElementOfType(diagnostic, KtExpression::class.java) ?: error("HAS_NEXT_FUNCTION_TYPE_MISMATCH reported on element that is not within any expression")
|
val expression = QuickFixUtil.getParentElementOfType(diagnostic, KtExpression::class.java)
|
||||||
val context = expression.analyze()
|
?: error("HAS_NEXT_FUNCTION_TYPE_MISMATCH reported on element that is not within any expression")
|
||||||
val resolvedCall = context.get(BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, expression) ?: return null
|
val context = expression.analyze(BodyResolveMode.PARTIAL)
|
||||||
|
val resolvedCall = context[BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, expression] ?: return null
|
||||||
val hasNextDescriptor = resolvedCall.candidateDescriptor
|
val hasNextDescriptor = resolvedCall.candidateDescriptor
|
||||||
val hasNextFunction = DescriptorToSourceUtils.descriptorToDeclaration(hasNextDescriptor) as KtFunction?
|
val hasNextFunction = DescriptorToSourceUtils.descriptorToDeclaration(hasNextDescriptor) as KtFunction? ?: return null
|
||||||
if (hasNextFunction != null) {
|
return ChangeFunctionReturnTypeFix(hasNextFunction, hasNextDescriptor.builtIns.booleanType)
|
||||||
return ChangeFunctionReturnTypeFix(hasNextFunction, hasNextDescriptor.builtIns.booleanType)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,11 +144,10 @@ class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinT
|
|||||||
return object : KotlinSingleIntentionActionFactory() {
|
return object : KotlinSingleIntentionActionFactory() {
|
||||||
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||||
val expression = QuickFixUtil.getParentElementOfType(diagnostic, KtBinaryExpression::class.java) ?: error("COMPARE_TO_TYPE_MISMATCH reported on element that is not within any expression")
|
val expression = QuickFixUtil.getParentElementOfType(diagnostic, KtBinaryExpression::class.java) ?: error("COMPARE_TO_TYPE_MISMATCH reported on element that is not within any expression")
|
||||||
val context = expression.analyze()
|
val context = expression.analyze(BodyResolveMode.PARTIAL)
|
||||||
val resolvedCall = expression.getResolvedCall(context) ?: return null
|
val resolvedCall = expression.getResolvedCall(context) ?: return null
|
||||||
val compareToDescriptor = resolvedCall.candidateDescriptor
|
val compareToDescriptor = resolvedCall.candidateDescriptor
|
||||||
val compareTo = DescriptorToSourceUtils.descriptorToDeclaration(compareToDescriptor)
|
val compareTo = DescriptorToSourceUtils.descriptorToDeclaration(compareToDescriptor) as? KtFunction ?: return null
|
||||||
if (compareTo !is KtFunction) return null
|
|
||||||
return ChangeFunctionReturnTypeFix(compareTo, compareToDescriptor.builtIns.intType)
|
return ChangeFunctionReturnTypeFix(compareTo, compareToDescriptor.builtIns.intType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,34 +156,34 @@ class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinT
|
|||||||
fun createFactoryForReturnTypeMismatchOnOverride(): KotlinIntentionActionsFactory {
|
fun createFactoryForReturnTypeMismatchOnOverride(): KotlinIntentionActionsFactory {
|
||||||
return object : KotlinIntentionActionsFactory() {
|
return object : KotlinIntentionActionsFactory() {
|
||||||
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
|
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
|
||||||
|
val function = QuickFixUtil.getParentElementOfType(diagnostic, KtFunction::class.java) ?: return emptyList()
|
||||||
|
|
||||||
val actions = LinkedList<IntentionAction>()
|
val actions = LinkedList<IntentionAction>()
|
||||||
|
|
||||||
val function = QuickFixUtil.getParentElementOfType(diagnostic, KtFunction::class.java)
|
val descriptor = function.resolveToDescriptor() as FunctionDescriptor
|
||||||
if (function != null) {
|
|
||||||
val descriptor = function.resolveToDescriptor() as FunctionDescriptor
|
|
||||||
|
|
||||||
val matchingReturnType = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(descriptor)
|
val matchingReturnType = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(descriptor)
|
||||||
if (matchingReturnType != null) {
|
if (matchingReturnType != null) {
|
||||||
actions.add(ChangeFunctionReturnTypeFix(function, matchingReturnType))
|
actions.add(ChangeFunctionReturnTypeFix(function, matchingReturnType))
|
||||||
}
|
}
|
||||||
|
|
||||||
val functionType = descriptor.returnType ?: return actions
|
val functionType = descriptor.returnType ?: return actions
|
||||||
|
|
||||||
val overriddenMismatchingFunctions = LinkedList<FunctionDescriptor>()
|
val overriddenMismatchingFunctions = LinkedList<FunctionDescriptor>()
|
||||||
for (overriddenFunction in descriptor.overriddenDescriptors) {
|
for (overriddenFunction in descriptor.overriddenDescriptors) {
|
||||||
val overriddenFunctionType = overriddenFunction.returnType ?: continue
|
val overriddenFunctionType = overriddenFunction.returnType ?: continue
|
||||||
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(functionType, overriddenFunctionType)) {
|
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(functionType, overriddenFunctionType)) {
|
||||||
overriddenMismatchingFunctions.add(overriddenFunction)
|
overriddenMismatchingFunctions.add(overriddenFunction)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overriddenMismatchingFunctions.size == 1) {
|
|
||||||
val overriddenFunction = DescriptorToSourceUtils.descriptorToDeclaration(overriddenMismatchingFunctions[0])
|
|
||||||
if (overriddenFunction is KtFunction) {
|
|
||||||
actions.add(ChangeFunctionReturnTypeFix(overriddenFunction, functionType))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (overriddenMismatchingFunctions.size == 1) {
|
||||||
|
val overriddenFunction = DescriptorToSourceUtils.descriptorToDeclaration(overriddenMismatchingFunctions[0])
|
||||||
|
if (overriddenFunction is KtFunction) {
|
||||||
|
actions.add(ChangeFunctionReturnTypeFix(overriddenFunction, functionType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,8 +201,8 @@ class ChangeFunctionReturnTypeFix(element: KtFunction, private val type: KotlinT
|
|||||||
fun createFactoryForChangingReturnTypeToNothing(): KotlinSingleIntentionActionFactory {
|
fun createFactoryForChangingReturnTypeToNothing(): KotlinSingleIntentionActionFactory {
|
||||||
return object : KotlinSingleIntentionActionFactory() {
|
return object : KotlinSingleIntentionActionFactory() {
|
||||||
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||||
val function = QuickFixUtil.getParentElementOfType(diagnostic, KtFunction::class.java)
|
val function = QuickFixUtil.getParentElementOfType(diagnostic, KtFunction::class.java) ?: return null
|
||||||
return if (function == null) null else ChangeFunctionReturnTypeFix(function, function.platform.builtIns.nothingType)
|
return ChangeFunctionReturnTypeFix(function, function.platform.builtIns.nothingType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user