Fix 'Redundant qualifier name' warnings & refactoring in idea

This commit is contained in:
Dmitry Gridin
2019-04-09 21:07:31 +07:00
parent 646f325f57
commit f3faae7bb4
50 changed files with 779 additions and 763 deletions
@@ -35,21 +35,21 @@ import javax.swing.JLabel
import javax.swing.JPanel
class KotlinGenerateEqualsWizard(
project: Project,
klass: KtClass,
properties: List<KtNamedDeclaration>,
needEquals: Boolean,
needHashCode: Boolean
project: Project,
klass: KtClass,
properties: List<KtNamedDeclaration>,
needEquals: Boolean,
needHashCode: Boolean
) : AbstractGenerateEqualsWizard<KtClass, KtNamedDeclaration, KotlinMemberInfo>(
project, KotlinGenerateEqualsWizard.BuilderImpl(klass, properties, needEquals, needHashCode)
project, BuilderImpl(klass, properties, needEquals, needHashCode)
) {
private object MemberInfoModelImpl : AbstractMemberInfoModel<KtNamedDeclaration, KotlinMemberInfo>()
private class BuilderImpl(
private val klass: KtClass,
properties: List<KtNamedDeclaration>,
needEquals: Boolean,
needHashCode: Boolean
private val klass: KtClass,
properties: List<KtNamedDeclaration>,
needEquals: Boolean,
needHashCode: Boolean
) : AbstractGenerateEqualsWizard.Builder<KtClass, KtNamedDeclaration, KotlinMemberInfo>() {
private val equalsPanel: KotlinMemberSelectionPanel?
private val hashCodePanel: KotlinMemberSelectionPanel?
@@ -60,13 +60,13 @@ class KotlinGenerateEqualsWizard(
init {
equalsPanel = if (needEquals) {
KotlinMemberSelectionPanel("Choose p&roperties to be included in equals()", memberInfos, null).apply {
KotlinMemberSelectionPanel("Choose properties to be included in equals()", memberInfos, null).apply {
table.memberInfoModel = MemberInfoModelImpl
}
} else null
hashCodePanel = if (needHashCode) {
KotlinMemberSelectionPanel("Choose p&roperties to be included in hashCode()", memberInfos, null).apply {
KotlinMemberSelectionPanel("Choose properties to be included in hashCode()", memberInfos, null).apply {
table.memberInfoModel = MemberInfoModelImpl
}
} else null
@@ -31,7 +31,7 @@ import java.awt.datatransfer.DataFlavor
import java.io.Serializable
class KotlinReferenceTransferableData(
val data: Array<KotlinReferenceData>
val data: Array<KotlinReferenceData>
) : TextBlockTransferableData, Cloneable, Serializable {
override fun getFlavor() = KotlinReferenceData.dataFlavor
@@ -56,15 +56,15 @@ class KotlinReferenceTransferableData(
return i
}
public override fun clone() = KotlinReferenceTransferableData(Array(data.size, { data[it].clone() }))
public override fun clone() = KotlinReferenceTransferableData(Array(data.size) { data[it].clone() })
}
class KotlinReferenceData(
var startOffset: Int,
var endOffset: Int,
val fqName: String,
val isQualifiable: Boolean,
val kind: KotlinReferenceData.Kind
var startOffset: Int,
var endOffset: Int,
val fqName: String,
val isQualifiable: Boolean,
val kind: Kind
) : Cloneable, Serializable {
enum class Kind {
@@ -87,8 +87,7 @@ class KotlinReferenceData(
public override fun clone(): KotlinReferenceData {
try {
return super.clone() as KotlinReferenceData
}
catch (e: CloneNotSupportedException) {
} catch (e: CloneNotSupportedException) {
throw RuntimeException()
}
}
@@ -97,14 +96,14 @@ class KotlinReferenceData(
val dataFlavor: DataFlavor? by lazy {
try {
val dataClass = KotlinReferenceData::class.java
DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + dataClass.name,
"KotlinReferenceData",
dataClass.classLoader)
}
catch (e: NoClassDefFoundError) {
DataFlavor(
DataFlavor.javaJVMLocalObjectMimeType + ";class=" + dataClass.name,
"KotlinReferenceData",
dataClass.classLoader
)
} catch (e: NoClassDefFoundError) {
null
}
catch (e: IllegalArgumentException) {
} catch (e: IllegalArgumentException) {
null
}
}
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.psi.*
class KotlinSpellcheckingStrategy : SpellcheckingStrategy() {
private val plainTextTokenizer = TokenizerBase<KtLiteralStringTemplateEntry>(PlainTextSplitter.getInstance())
private val emptyTokenizer = SpellcheckingStrategy.EMPTY_TOKENIZER
private val emptyTokenizer = EMPTY_TOKENIZER
override fun getTokenizer(element: PsiElement?): Tokenizer<out PsiElement?> {
return when (element) {
@@ -44,7 +44,7 @@ class KotlinMigrationProjectComponent(val project: Project) {
init {
val connection = project.messageBus.connect()
connection.subscribe(ProjectDataImportListener.TOPIC, ProjectDataImportListener {
KotlinMigrationProjectComponent.getInstanceIfNotDisposed(project)?.onImportFinished()
getInstanceIfNotDisposed(project)?.onImportFinished()
})
}
@@ -165,8 +165,7 @@ class KotlinMigrationProjectComponent(val project: Project) {
val changedFiles = ChangeListManager.getInstance(project).affectedPaths
for (changedFile in changedFiles) {
val extension = changedFile.extension
when (extension) {
when (changedFile.extension) {
"gradle" -> return true
"properties" -> return true
"kts" -> return true
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.idea.editor
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegate
import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegate.Result
import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegateAdapter
import com.intellij.injected.editor.EditorWindow
@@ -55,7 +54,7 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
override fun preprocessEnter(
file: PsiFile, editor: Editor, caretOffset: Ref<Int>, caretAdvance: Ref<Int>, dataContext: DataContext,
originalHandler: EditorActionHandler?
): EnterHandlerDelegate.Result {
): Result {
val offset = caretOffset.get().toInt()
if (editor !is EditorWindow) {
return preprocessEnter(file, editor, offset, originalHandler, dataContext)
@@ -194,7 +193,7 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
val marginCharToInsert = if (marginChar != null &&
!prefixStripped.startsWith(marginChar) &&
!nonBlankNotFirstLines.isEmpty() &&
nonBlankNotFirstLines.isNotEmpty() &&
nonBlankNotFirstLines.none { it.trimStart().startsWith(marginChar) }
) {
@@ -242,11 +241,11 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
}
companion object {
val DEFAULT_TRIM_MARGIN_CHAR = '|'
val TRIM_INDENT_CALL = "trimIndent"
val TRIM_MARGIN_CALL = "trimMargin"
const val DEFAULT_TRIM_MARGIN_CHAR = '|'
const val TRIM_INDENT_CALL = "trimIndent"
const val TRIM_MARGIN_CALL = "trimMargin"
val MULTILINE_QUOTE = "\"\"\""
const val MULTILINE_QUOTE = "\"\"\""
class MultilineSettings(project: Project) {
private val kotlinIndentOptions =
@@ -286,7 +285,7 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
else -> return null
}
return element.parents.firstIsInstanceOrNull<KtStringTemplateExpression>()
return element.parents.firstIsInstanceOrNull()
}
fun inMultilineString(element: PsiElement?, offset: Int) =
@@ -54,9 +54,9 @@ class KotlinCodeBlockSelectioner : ExtendWordSelectionHandlerBase() {
val start = findBlockContentStart(block)
val end = findBlockContentEnd(block)
if (end > start) {
result.addAll(ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, TextRange(start, end)))
result.addAll(expandToWholeLine(editorText, TextRange(start, end)))
}
result.addAll(ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, block.textRange!!))
result.addAll(expandToWholeLine(editorText, block.textRange!!))
return result
}
@@ -26,6 +26,6 @@ class KotlinDocCommentSelectioner : ExtendWordSelectionHandlerBase() {
override fun canSelect(e: PsiElement) = e is KDoc
override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List<TextRange>? {
return ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, e.textRange)
return expandToWholeLine(editorText, e.textRange)
}
}
@@ -18,8 +18,8 @@ import kotlin.reflect.KProperty
class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider() {
override fun getLanguage() = KotlinLanguage.INSTANCE
override fun getCodeSample(settingsType: LanguageCodeStyleSettingsProvider.SettingsType): String = when (settingsType) {
LanguageCodeStyleSettingsProvider.SettingsType.WRAPPING_AND_BRACES_SETTINGS ->
override fun getCodeSample(settingsType: SettingsType): String = when (settingsType) {
SettingsType.WRAPPING_AND_BRACES_SETTINGS ->
"""
@Deprecated("Foo") public class ThisIsASampleClass : Comparable<*>, Appendable {
val test =
@@ -71,7 +71,7 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
fun veryLongExpressionBodyMethod() = "abc"
""".trimIndent()
LanguageCodeStyleSettingsProvider.SettingsType.BLANK_LINES_SETTINGS ->
SettingsType.BLANK_LINES_SETTINGS ->
"""
class Foo {
private var field1: Int = 1
@@ -169,13 +169,13 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
override fun getLanguageName(): String = KotlinLanguage.NAME
override fun customizeSettings(consumer: CodeStyleSettingsCustomizable, settingsType: LanguageCodeStyleSettingsProvider.SettingsType) {
override fun customizeSettings(consumer: CodeStyleSettingsCustomizable, settingsType: SettingsType) {
fun showCustomOption(field: KProperty<*>, title: String, groupName: String? = null, vararg options: Any) {
consumer.showCustomOption(KotlinCodeStyleSettings::class.java, field.name, title, groupName, *options)
}
when (settingsType) {
LanguageCodeStyleSettingsProvider.SettingsType.SPACING_SETTINGS -> {
SettingsType.SPACING_SETTINGS -> {
consumer.showStandardOptions(
"SPACE_AROUND_ASSIGNMENT_OPERATORS",
"SPACE_AROUND_LOGICAL_OPERATORS",
@@ -190,7 +190,7 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
"SPACE_BEFORE_WHILE_PARENTHESES",
"SPACE_BEFORE_FOR_PARENTHESES",
"SPACE_BEFORE_CATCH_PARENTHESES"
);
)
showCustomOption(
KotlinCodeStyleSettings::SPACE_AROUND_RANGE,
@@ -252,7 +252,7 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
CodeStyleSettingsCustomizable.SPACES_BEFORE_PARENTHESES
)
}
LanguageCodeStyleSettingsProvider.SettingsType.WRAPPING_AND_BRACES_SETTINGS -> {
SettingsType.WRAPPING_AND_BRACES_SETTINGS -> {
consumer.showStandardOptions(
// "ALIGN_MULTILINE_CHAINED_METHODS",
"RIGHT_MARGIN",
@@ -364,7 +364,7 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
CodeStyleSettingsCustomizable.WRAPPING_IF_STATEMENT
)
}
LanguageCodeStyleSettingsProvider.SettingsType.BLANK_LINES_SETTINGS -> {
SettingsType.BLANK_LINES_SETTINGS -> {
consumer.showStandardOptions(
"KEEP_BLANK_LINES_IN_CODE",
"KEEP_BLANK_LINES_IN_DECLARATIONS",
@@ -377,8 +377,8 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
CodeStyleSettingsCustomizable.BLANK_LINES
)
}
LanguageCodeStyleSettingsProvider.SettingsType.COMMENTER_SETTINGS -> {
consumer.showAllStandardOptions();
SettingsType.COMMENTER_SETTINGS -> {
consumer.showAllStandardOptions()
}
else -> consumer.showStandardOptions()
}
@@ -16,8 +16,8 @@
package org.jetbrains.kotlin.idea.goto
import com.intellij.ide.util.DefaultPsiElementCellRenderer
import com.intellij.ide.util.PlatformModuleRendererFactory
import com.intellij.ide.util.PsiElementListCellRenderer
import com.intellij.ide.util.gotoByName.GotoFileCellRenderer
import com.intellij.navigation.NavigationItem
import com.intellij.openapi.util.Iconable
@@ -30,7 +30,6 @@ import com.intellij.ui.ColoredListCellRenderer
import com.intellij.ui.JBColor
import com.intellij.ui.SimpleTextAttributes
import com.intellij.util.ui.FilePathSplittingPolicy
import com.intellij.ide.util.DefaultPsiElementCellRenderer
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.KtNamedFunction
@@ -58,8 +57,8 @@ internal class KotlinSearchEverywherePsiRenderer(private val myList: JList<*>) :
layout = object : BorderLayout() {
override fun layoutContainer(target: Container) {
super.layoutContainer(target)
val right = getLayoutComponent(BorderLayout.EAST)
val left = getLayoutComponent(BorderLayout.WEST)
val right = getLayoutComponent(EAST)
val left = getLayoutComponent(WEST)
//IDEA-140824
if (right != null && left != null && left.bounds.x + left.bounds.width > right.bounds.x) {
@@ -96,10 +95,10 @@ internal class KotlinSearchEverywherePsiRenderer(private val myList: JList<*>) :
var width = myList.width
if (width == 0) width += 800
val path = FilePathSplittingPolicy.SPLIT_BY_SEPARATOR.getOptimalTextForComponent(
name,
File(relativePath),
this,
width - myRightComponentWidth - 16 - 10
name,
File(relativePath),
this,
width - myRightComponentWidth - 16 - 10
)
return "($path)"
}
@@ -37,7 +37,7 @@ import javax.swing.JPanel
import javax.swing.JTree
class KotlinOverrideHierarchyBrowser(
project: Project, baseElement: PsiElement
project: Project, baseElement: PsiElement
) : MethodHierarchyBrowserBase(project, baseElement) {
override fun createTrees(trees: MutableMap<String, JTree>) {
val actionManager = ActionManager.getInstance()
@@ -49,25 +49,25 @@ class KotlinOverrideHierarchyBrowser(
BaseOnThisMethodAction().registerCustomShortcutSet(actionManager.getAction(IdeActions.ACTION_METHOD_HIERARCHY).shortcutSet, tree)
trees.put(MethodHierarchyBrowserBase.METHOD_TYPE, tree)
trees[METHOD_TYPE] = tree
}
override fun createLegendPanel(): JPanel? =
MethodHierarchyBrowserBase.createStandardLegendPanel(
KotlinBundle.message("hierarchy.legend.member.is.defined.in.class"),
KotlinBundle.message("hierarchy.legend.member.defined.in.superclass"),
KotlinBundle.message("hierarchy.legend.member.should.be.defined")
)
createStandardLegendPanel(
KotlinBundle.message("hierarchy.legend.member.is.defined.in.class"),
KotlinBundle.message("hierarchy.legend.member.defined.in.superclass"),
KotlinBundle.message("hierarchy.legend.member.should.be.defined")
)
override fun getElementFromDescriptor(descriptor: HierarchyNodeDescriptor) = descriptor.psiElement
override fun isApplicableElement(psiElement: PsiElement): Boolean =
psiElement.isOverrideHierarchyElement()
psiElement.isOverrideHierarchyElement()
override fun createHierarchyTreeStructure(typeName: String, psiElement: PsiElement): HierarchyTreeStructure? =
if (typeName == MethodHierarchyBrowserBase.METHOD_TYPE) KotlinOverrideTreeStructure(myProject, psiElement as KtCallableDeclaration) else null
if (typeName == METHOD_TYPE) KotlinOverrideTreeStructure(myProject, psiElement as KtCallableDeclaration) else null
override fun getComparator() = JavaHierarchyUtil.getComparator(myProject)!!
override fun getComparator() = JavaHierarchyUtil.getComparator(myProject)
override fun getContentDisplayName(typeName: String, element: PsiElement): String? {
val targetElement = element.unwrapped
@@ -28,8 +28,8 @@ import com.intellij.psi.PsiMember
import com.intellij.ui.LayeredIcon
import com.intellij.ui.RowIcon
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMemberDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMemberDescriptor
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -39,10 +39,10 @@ import org.jetbrains.kotlin.util.findCallableMemberBySignature
import java.awt.Font
import javax.swing.Icon
class KotlinOverrideHierarchyNodeDescriptor (
parentNode: HierarchyNodeDescriptor?,
klass: PsiElement,
baseElement: PsiElement
class KotlinOverrideHierarchyNodeDescriptor(
parentNode: HierarchyNodeDescriptor?,
klass: PsiElement,
baseElement: PsiElement
) : HierarchyNodeDescriptor(klass.project, parentNode, klass, parentNode == null) {
private val baseElement = baseElement.createSmartPointer()
@@ -79,7 +79,8 @@ class KotlinOverrideHierarchyNodeDescriptor (
}
val isAbstractClass = classDescriptor.modality == Modality.ABSTRACT
val hasBaseImplementation = DescriptorUtils.getAllOverriddenDeclarations(callableDescriptor).any { it.modality != Modality.ABSTRACT }
val hasBaseImplementation =
DescriptorUtils.getAllOverriddenDeclarations(callableDescriptor).any { it.modality != Modality.ABSTRACT }
return if (isAbstractClass || hasBaseImplementation) AllIcons.Hierarchy.MethodNotDefined else AllIcons.Hierarchy.ShouldDefineMethod
}
@@ -115,7 +116,7 @@ class KotlinOverrideHierarchyNodeDescriptor (
if (myIsBase) {
val icon = LayeredIcon(2)
icon.setIcon(newIcon, 0)
icon.setIcon(AllIcons.Hierarchy.Base, 1, -AllIcons.Hierarchy.Base.iconWidth / 2, 0)
icon.setIcon(AllIcons.Actions.Forward, 1, -AllIcons.Actions.Forward.iconWidth / 2, 0)
newIcon = icon
}
@@ -134,7 +135,7 @@ class KotlinOverrideHierarchyNodeDescriptor (
classNameAttributes = TextAttributes(myColor, null, null, null, Font.PLAIN)
}
with (myHighlightedText.ending) {
with(myHighlightedText.ending) {
addText(classDescriptor.name.asString(), classNameAttributes)
classDescriptor.parents.forEach { parentDescriptor ->
when (parentDescriptor) {
@@ -145,7 +146,7 @@ class KotlinOverrideHierarchyNodeDescriptor (
}
}
is PackageFragmentDescriptor -> {
addText(" (${parentDescriptor.fqName.asString()})", HierarchyNodeDescriptor.getPackageNameAttributes())
addText(" (${parentDescriptor.fqName.asString()})", getPackageNameAttributes())
return@forEach
}
}
@@ -36,7 +36,7 @@ class KotlinRunLineMarkerContributor : RunLineMarkerContributor() {
val platform = function.containingKtFile.module?.platform ?: return null
if (!platform.kind.tooling.acceptsAsEntryPoint(function)) return null
return RunLineMarkerContributor.Info(AllIcons.RunConfigurations.TestState.Run, null, ExecutorAction.getActions(0))
return Info(AllIcons.RunConfigurations.TestState.Run, null, ExecutorAction.getActions(0))
}
return null
@@ -40,8 +40,7 @@ class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() {
fun getTestStateIcon(url: String, project: Project): Icon? {
val defaultIcon = AllIcons.RunConfigurations.TestState.Run
val state = TestStateStorage.getInstance(project).getState(url) ?: return defaultIcon
val magnitude = TestIconMapper.getMagnitude(state.magnitude)
return when (magnitude) {
return when (TestIconMapper.getMagnitude(state.magnitude)) {
TestStateInfo.Magnitude.ERROR_INDEX,
TestStateInfo.Magnitude.FAILED_INDEX -> AllIcons.RunConfigurations.TestState.Red2
TestStateInfo.Magnitude.PASSED_INDEX,
@@ -51,7 +50,7 @@ class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() {
}
}
override fun getInfo(element: PsiElement): RunLineMarkerContributor.Info? {
override fun getInfo(element: PsiElement): Info? {
val declaration = element.getStrictParentOfType<KtNamedDeclaration>() ?: return null
if (declaration.nameIdentifier != element) return null
@@ -64,6 +63,6 @@ class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() {
val targetPlatform = declaration.module?.platform ?: return null
val icon = targetPlatform.kind.tooling.getTestIcon(declaration, descriptor) ?: return null
return RunLineMarkerContributor.Info(icon, { "Run Test" }, ExecutorAction.getActions())
return Info(icon, { "Run Test" }, ExecutorAction.getActions())
}
}
@@ -26,15 +26,18 @@ class RecursivePropertyAccessorInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
return simpleNameExpressionVisitor { expression ->
if (isRecursivePropertyAccess(expression)) {
holder.registerProblem(expression,
"Recursive property accessor",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
ReplaceWithFieldFix())
}
else if (isRecursiveSyntheticPropertyAccess(expression)) {
holder.registerProblem(expression,
"Recursive synthetic property accessor",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING)
holder.registerProblem(
expression,
"Recursive property accessor",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
ReplaceWithFieldFix()
)
} else if (isRecursiveSyntheticPropertyAccess(expression)) {
holder.registerProblem(
expression,
"Recursive synthetic property accessor",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING
)
}
}
}
@@ -55,7 +58,7 @@ class RecursivePropertyAccessorInspection : AbstractKotlinInspection() {
companion object {
private fun KtBinaryExpression?.isAssignmentTo(expression: KtSimpleNameExpression): Boolean =
this != null && KtPsiUtil.isAssignment(this) && PsiTreeUtil.isAncestor(left, expression, false)
this != null && KtPsiUtil.isAssignment(this) && PsiTreeUtil.isAncestor(left, expression, false)
private fun isSameAccessor(expression: KtSimpleNameExpression, isGetter: Boolean): Boolean {
val binaryExpr = expression.getStrictParentOfType<KtBinaryExpression>()
@@ -64,8 +67,7 @@ class RecursivePropertyAccessorInspection : AbstractKotlinInspection() {
return KtTokens.AUGMENTED_ASSIGNMENTS.contains(binaryExpr?.operationToken)
}
return true
}
else /* isSetter */ {
} else /* isSetter */ {
if (binaryExpr.isAssignmentTo(expression)) {
return true
}
@@ -84,7 +86,7 @@ class RecursivePropertyAccessorInspection : AbstractKotlinInspection() {
if (element.parent is KtCallableReferenceExpression) return false
val bindingContext = element.analyze()
val target = bindingContext[REFERENCE_TARGET, element]
if (target != bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, propertyAccessor.property]) return false
if (target != bindingContext[DECLARATION_TO_DESCRIPTOR, propertyAccessor.property]) return false
(element.parent as? KtQualifiedExpression)?.let {
if (it.receiverExpression.text != KtTokens.THIS_KEYWORD.value && !it.hasObjectReceiver(bindingContext)) return false
}
@@ -104,11 +106,12 @@ class RecursivePropertyAccessorInspection : AbstractKotlinInspection() {
val syntheticDescriptor = bindingContext[REFERENCE_TARGET, element] as? SyntheticJavaPropertyDescriptor ?: return false
val namedFunctionDescriptor = bindingContext[DECLARATION_TO_DESCRIPTOR, namedFunction]
if (namedFunctionDescriptor != syntheticDescriptor.getMethod &&
namedFunctionDescriptor != syntheticDescriptor.setMethod) return false
namedFunctionDescriptor != syntheticDescriptor.setMethod
) return false
return isSameAccessor(element, isGetter)
}
private fun KtQualifiedExpression.hasObjectReceiver(context: BindingContext) : Boolean {
private fun KtQualifiedExpression.hasObjectReceiver(context: BindingContext): Boolean {
val receiver = receiverExpression as? KtReferenceExpression ?: return false
return (context[REFERENCE_TARGET, receiver] as? ClassDescriptor)?.kind == ClassKind.OBJECT
}
@@ -88,7 +88,7 @@ class ReformatInspection : LocalInspectionTool() {
}
private fun isEmptyLineReformat(whitespace: PsiWhiteSpace, change: FormattingChange): Boolean {
if (change !is FormattingChange.ReplaceWhiteSpace) return false
if (change !is ReplaceWhiteSpace) return false
val beforeText = whitespace.text
val afterText = change.whiteSpace
@@ -55,7 +55,7 @@ class FoldInitializerAndIfToElvisIntention :
}
override fun applyTo(element: KtIfExpression, editor: Editor?) {
val newElvis = FoldInitializerAndIfToElvisIntention.applyTo(element)
val newElvis = applyTo(element)
editor?.caretModel?.moveToOffset(newElvis.right!!.textOffset)
}
@@ -29,16 +29,16 @@ import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
import org.jetbrains.kotlin.psi.KtFile
class KDocTypedHandler : TypedHandlerDelegate() {
override fun beforeCharTyped(c: Char, project: Project, editor: Editor, file: PsiFile, fileType: FileType): TypedHandlerDelegate.Result {
override fun beforeCharTyped(c: Char, project: Project, editor: Editor, file: PsiFile, fileType: FileType): Result {
if (overwriteClosingBracket(c, editor, file)) {
EditorModificationUtil.moveCaretRelatively(editor, 1)
return TypedHandlerDelegate.Result.STOP
return Result.STOP
}
return TypedHandlerDelegate.Result.CONTINUE
return Result.CONTINUE
}
override fun charTyped(c: Char, project: Project, editor: Editor, file: PsiFile): TypedHandlerDelegate.Result =
if (handleBracketTyped(c, project, editor, file)) TypedHandlerDelegate.Result.STOP else TypedHandlerDelegate.Result.CONTINUE
override fun charTyped(c: Char, project: Project, editor: Editor, file: PsiFile): Result =
if (handleBracketTyped(c, project, editor, file)) Result.STOP else Result.CONTINUE
private fun overwriteClosingBracket(c: Char, editor: Editor, file: PsiFile): Boolean {
if (c != ']' && c != ')') return false
@@ -18,11 +18,11 @@ interface Template<in TOuter> {
* A placeholder that is inserted inside [TOuter]
*/
open class Placeholder<TOuter> {
private var contentStack = mutableListOf<(TOuter.(Placeholder<TOuter>.Exec) -> Unit)>()
private var contentStack = mutableListOf<(TOuter.(Exec) -> Unit)>()
var meta: String = ""
operator fun invoke(meta: String = "", content: TOuter.(Placeholder<TOuter>.Exec) -> Unit) {
operator fun invoke(meta: String = "", content: TOuter.(Exec) -> Unit) {
this.contentStack.add(content)
this.meta = meta
}
@@ -48,10 +48,10 @@ open class Placeholder<TOuter> {
/**
* Placeholder that can appear multiple times
*/
open class PlaceholderList<TOuter, TInner>() {
open class PlaceholderList<TOuter, TInner> {
private var items = ArrayList<PlaceholderItem<TInner>>()
operator fun invoke(meta: String = "", content: TInner.(Placeholder<TInner>.Exec) -> Unit = {}) {
val placeholder = PlaceholderItem<TInner>(items.size, items)
val placeholder = PlaceholderItem(items.size, items)
placeholder(meta, content)
items.add(placeholder)
}
@@ -76,7 +76,7 @@ class PlaceholderItem<TOuter>(val index: Int, val collection: List<PlaceholderIt
/**
* Inserts every element of placeholder list
*/
fun <TOuter, TInner> TOuter.each(items: PlaceholderList<TOuter, TInner>, itemTemplate: TOuter.(PlaceholderItem<TInner>) -> Unit): Unit {
fun <TOuter, TInner> TOuter.each(items: PlaceholderList<TOuter, TInner>, itemTemplate: TOuter.(PlaceholderItem<TInner>) -> Unit) {
items.apply(this, itemTemplate)
}
@@ -101,10 +101,10 @@ open class TemplatePlaceholder<TTemplate> {
fun <TTemplate : Template<TOuter>, TOuter> TOuter.insert(template: TTemplate, placeholder: TemplatePlaceholder<TTemplate>) {
placeholder.apply(template)
with (template) { apply() }
with(template) { apply() }
}
fun <TOuter, TTemplate : Template<TOuter>> TOuter.insert(template: TTemplate, build: TTemplate.() -> Unit) {
template.build()
with (template) { apply() }
with(template) { apply() }
}
@@ -268,7 +268,7 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
val color = if (isResolvedToDescriptor(call, itemToShow, bindingContext))
KotlinParameterInfoWithCallHandlerBase.GREEN_BACKGROUND
GREEN_BACKGROUND
else
context.defaultParameterColor
@@ -118,7 +118,7 @@ enum class HintType(val desc: String, defaultEnabled: Boolean) {
companion object {
fun resolve(elem: PsiElement): HintType? {
val applicableTypes = HintType.values().filter { it.isApplicable(elem) }
val applicableTypes = values().filter { it.isApplicable(elem) }
return applicableTypes.firstOrNull()
}
@@ -153,8 +153,7 @@ class KotlinInlayParameterHintsProvider : InlayParameterHintsProvider {
)
override fun getHintInfo(element: PsiElement): HintInfo? {
val hintType = HintType.resolve(element) ?: return null
return when (hintType) {
return when (val hintType = HintType.resolve(element) ?: return null) {
HintType.PARAMETER_HINT -> {
val parent = (element as? KtValueArgumentList)?.parent
(parent as? KtCallElement)?.let { getMethodInfo(it) }
@@ -31,12 +31,12 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.TemplateKind
import org.jetbrains.kotlin.idea.core.getFunctionBodyTextFromTemplate
import org.jetbrains.kotlin.idea.core.implicitModality
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.psi.*
@@ -48,7 +48,7 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
class AddFunctionToSupertypeFix private constructor(
element: KtNamedFunction,
private val functions: List<AddFunctionToSupertypeFix.FunctionData>
private val functions: List<FunctionData>
) : KotlinQuickFixAction<KtNamedFunction>(element), LowPriorityAction {
init {
@@ -90,7 +90,7 @@ class AddFunctionToSupertypeFix private constructor(
ShortenReferences.DEFAULT.process(insertedFunctionElement)
val modifierToken = insertedFunctionElement.modalityModifier()?.node?.elementType as? KtModifierKeywordToken
?: return@executeWriteCommand
?: return@executeWriteCommand
if (insertedFunctionElement.implicitModality() == modifierToken) {
RemoveModifierFix(insertedFunctionElement, modifierToken, true).invoke()
}
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.idea.inspections.KotlinUniversalQuickFix
import org.jetbrains.kotlin.idea.refactoring.canRefactor
import org.jetbrains.kotlin.idea.util.runOnExpectAndAllActuals
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
@@ -49,7 +48,7 @@ open class AddModifierFix(
) : KotlinCrossLanguageQuickFixAction<KtModifierListOwner>(element), KotlinUniversalQuickFix {
override fun getText(): String {
val element = element ?: return ""
if (modifier in modalityModifiers || modifier in KtTokens.VISIBILITY_MODIFIERS || modifier == KtTokens.CONST_KEYWORD) {
if (modifier in modalityModifiers || modifier in VISIBILITY_MODIFIERS || modifier == CONST_KEYWORD) {
return "Make ${getElementName(element)} ${modifier.value}"
}
return "Add '${modifier.value}' modifier"
@@ -60,10 +59,10 @@ open class AddModifierFix(
private fun invokeOnElement(element: KtModifierListOwner?) {
element?.addModifier(modifier)
if (modifier == KtTokens.ABSTRACT_KEYWORD && (element is KtProperty || element is KtNamedFunction)) {
if (modifier == ABSTRACT_KEYWORD && (element is KtProperty || element is KtNamedFunction)) {
element.containingClass()?.run {
if (!hasModifier(KtTokens.ABSTRACT_KEYWORD) && !hasModifier(KtTokens.SEALED_KEYWORD)) {
addModifier(KtTokens.ABSTRACT_KEYWORD)
if (!hasModifier(ABSTRACT_KEYWORD) && !hasModifier(SEALED_KEYWORD)) {
addModifier(ABSTRACT_KEYWORD)
}
}
}
@@ -85,7 +84,7 @@ open class AddModifierFix(
companion object {
private fun KtModifierKeywordToken.isMultiplatformPersistent(): Boolean =
this in KtTokens.MODALITY_MODIFIERS || this == KtTokens.INLINE_KEYWORD
this in MODALITY_MODIFIERS || this == INLINE_KEYWORD
private val modalityModifiers = setOf(ABSTRACT_KEYWORD, OPEN_KEYWORD, FINAL_KEYWORD)
@@ -133,7 +132,7 @@ open class AddModifierFix(
}
if (modifier == ABSTRACT_KEYWORD
&& modifierListOwner is KtClass
&& modifierListOwner.hasModifier(KtTokens.INLINE_KEYWORD)
&& modifierListOwner.hasModifier(INLINE_KEYWORD)
) return null
}
INNER_KEYWORD -> {
@@ -158,7 +157,7 @@ open class AddModifierFix(
val typeReference = diagnostic.psiElement as KtTypeReference
val declaration = typeReference.classForRefactor() ?: return null
if (declaration.isEnum() || declaration.isData()) return null
return AddModifierFix(declaration, KtTokens.OPEN_KEYWORD)
return AddModifierFix(declaration, OPEN_KEYWORD)
}
}
@@ -173,7 +172,7 @@ open class AddModifierFix(
if (TypeUtils.isNullableType(type)) return null
if (KotlinBuiltIns.isPrimitiveType(type)) return null
return AddModifierFix(property, KtTokens.LATEINIT_KEYWORD)
return AddModifierFix(property, LATEINIT_KEYWORD)
}
}
}
@@ -48,8 +48,8 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit
import java.util.*
abstract class ChangeCallableReturnTypeFix(
element: KtCallableDeclaration,
type: KotlinType
element: KtCallableDeclaration,
type: KotlinType
) : KotlinQuickFixAction<KtCallableDeclaration>(element) {
private val changeFunctionLiteralReturnTypeFix: ChangeFunctionLiteralReturnTypeFix?
@@ -61,10 +61,10 @@ abstract class ChangeCallableReturnTypeFix(
init {
changeFunctionLiteralReturnTypeFix = if (element is KtFunctionLiteral) {
val functionLiteralExpression = PsiTreeUtil.getParentOfType(element, KtLambdaExpression::class.java) ?: error("FunctionLiteral outside any FunctionLiteralExpression: " + element.getElementTextWithContext())
val functionLiteralExpression = PsiTreeUtil.getParentOfType(element, KtLambdaExpression::class.java)
?: error("FunctionLiteral outside any FunctionLiteralExpression: " + element.getElementTextWithContext())
ChangeFunctionLiteralReturnTypeFix(functionLiteralExpression, type)
}
else {
} else {
null
}
}
@@ -80,8 +80,7 @@ abstract class ChangeCallableReturnTypeFix(
return "property $fullName"
}
return "function $fullName"
}
else {
} else {
return null
}
}
@@ -139,7 +138,7 @@ abstract class ChangeCallableReturnTypeFix(
override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean {
return !typeContainsError &&
element !is KtConstructor<*>
element !is KtConstructor<*>
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
@@ -147,14 +146,12 @@ abstract class ChangeCallableReturnTypeFix(
if (changeFunctionLiteralReturnTypeFix != null) {
changeFunctionLiteralReturnTypeFix.invoke(project, editor!!, file)
}
else {
} else {
if (!(isUnitType && element is KtFunction && element.hasBlockBody())) {
var newTypeRef = KtPsiFactory(project).createType(typeSourceCode)
newTypeRef = element.setTypeReference(newTypeRef)!!
ShortenReferences.DEFAULT.process(newTypeRef)
}
else {
} else {
element.typeReference = null
}
}
@@ -166,32 +163,33 @@ abstract class ChangeCallableReturnTypeFix(
val context = entry.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = context.get(BindingContext.COMPONENT_RESOLVED_CALL, entry) ?: return null
val componentFunction =
DescriptorToSourceUtils.descriptorToDeclaration(resolvedCall.candidateDescriptor) as? KtCallableDeclaration
DescriptorToSourceUtils.descriptorToDeclaration(resolvedCall.candidateDescriptor) as? KtCallableDeclaration
?: return null
val expectedType = context[BindingContext.TYPE, entry.typeReference!!] ?: return null
return ChangeCallableReturnTypeFix.ForCalled(componentFunction, expectedType)
return ForCalled(componentFunction, expectedType)
}
}
object HasNextFunctionTypeMismatchFactory : KotlinSingleIntentionActionFactory() {
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")
?: error("HAS_NEXT_FUNCTION_TYPE_MISMATCH reported on element that is not within any expression")
val context = expression.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = context[BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, expression] ?: return null
val hasNextDescriptor = resolvedCall.candidateDescriptor
val hasNextFunction = DescriptorToSourceUtils.descriptorToDeclaration(hasNextDescriptor) as KtFunction? ?: return null
return ChangeCallableReturnTypeFix.ForCalled(hasNextFunction, hasNextDescriptor.builtIns.booleanType)
return ForCalled(hasNextFunction, hasNextDescriptor.builtIns.booleanType)
}
}
object CompareToTypeMismatchFactory : KotlinSingleIntentionActionFactory() {
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 resolvedCall = expression.resolveToCall() ?: return null
val compareToDescriptor = resolvedCall.candidateDescriptor
val compareTo = DescriptorToSourceUtils.descriptorToDeclaration(compareToDescriptor) as? KtFunction ?: return null
return ChangeCallableReturnTypeFix.ForCalled(compareTo, compareToDescriptor.builtIns.intType)
return ForCalled(compareTo, compareToDescriptor.builtIns.intType)
}
}
@@ -205,7 +203,7 @@ abstract class ChangeCallableReturnTypeFix(
val matchingReturnType = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(descriptor)
if (matchingReturnType != null) {
actions.add(ChangeCallableReturnTypeFix.OnType(function, matchingReturnType))
actions.add(OnType(function, matchingReturnType))
}
val functionType = descriptor.returnType ?: return actions
@@ -221,7 +219,7 @@ abstract class ChangeCallableReturnTypeFix(
if (overriddenMismatchingFunctions.size == 1) {
val overriddenFunction = DescriptorToSourceUtils.descriptorToDeclaration(overriddenMismatchingFunctions[0])
if (overriddenFunction is KtFunction) {
actions.add(ChangeCallableReturnTypeFix.ForOverridden(overriddenFunction, functionType))
actions.add(ForOverridden(overriddenFunction, functionType))
}
}
@@ -232,14 +230,14 @@ abstract class ChangeCallableReturnTypeFix(
object ChangingReturnTypeToUnitFactory : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val function = QuickFixUtil.getParentElementOfType(diagnostic, KtFunction::class.java) ?: return null
return ChangeCallableReturnTypeFix.ForEnclosing(function, function.builtIns.unitType)
return ForEnclosing(function, function.builtIns.unitType)
}
}
object ChangingReturnTypeToNothingFactory : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val function = QuickFixUtil.getParentElementOfType(diagnostic, KtFunction::class.java) ?: return null
return ChangeCallableReturnTypeFix.ForEnclosing(function, function.builtIns.nothingType)
return ForEnclosing(function, function.builtIns.nothingType)
}
}
@@ -247,7 +245,8 @@ abstract class ChangeCallableReturnTypeFix(
fun getDestructuringDeclarationEntryThatTypeMismatchComponentFunction(diagnostic: Diagnostic): KtDestructuringDeclarationEntry {
val componentName = COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.cast(diagnostic).a
val componentIndex = DataClassDescriptorResolver.getComponentIndex(componentName.asString())
val multiDeclaration = QuickFixUtil.getParentElementOfType(diagnostic, KtDestructuringDeclaration::class.java) ?: error("COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH reported on expression that is not within any multi declaration")
val multiDeclaration = QuickFixUtil.getParentElementOfType(diagnostic, KtDestructuringDeclaration::class.java)
?: error("COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH reported on expression that is not within any multi declaration")
return multiDeclaration.entries[componentIndex - 1]
}
}
@@ -51,8 +51,7 @@ open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinTyp
val container = element.unsafeResolveToDescriptor().containingDeclaration as? ClassDescriptor
val containerName = container?.name?.takeUnless { it.isSpecial }?.asString()
if (containerName != null) "'$containerName.$name'" else "'$name'"
}
else {
} else {
null
}
}
@@ -63,8 +62,7 @@ open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinTyp
val variablePresentation = variablePresentation()
return if (variablePresentation != null) {
"Change type of $variablePresentation to '$typePresentation'"
}
else {
} else {
"Change type to '$typePresentation'"
}
}
@@ -80,11 +78,9 @@ open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinTyp
}
}
override fun getFamilyName()
= KotlinBundle.message("change.type.family")
override fun getFamilyName() = KotlinBundle.message("change.type.family")
override fun isAvailable(project: Project, editor: Editor?, file: KtFile)
= !typeContainsError
override fun isAvailable(project: Project, editor: Editor?, file: KtFile) = !typeContainsError
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
@@ -141,25 +137,29 @@ open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinTyp
if (overriddenPropertyType != null) {
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(propertyType, overriddenPropertyType)) {
overriddenMismatchingProperties.add(overriddenProperty)
}
else if (overriddenProperty.isVar && !KotlinTypeChecker.DEFAULT.equalTypes(overriddenPropertyType, propertyType)) {
} else if (overriddenProperty.isVar && !KotlinTypeChecker.DEFAULT.equalTypes(
overriddenPropertyType,
propertyType
)
) {
canChangeOverriddenPropertyType = false
}
if (overriddenProperty.isVar && lowerBoundOfOverriddenPropertiesTypes != null &&
!KotlinTypeChecker.DEFAULT.equalTypes(lowerBoundOfOverriddenPropertiesTypes, overriddenPropertyType)) {
!KotlinTypeChecker.DEFAULT.equalTypes(lowerBoundOfOverriddenPropertiesTypes, overriddenPropertyType)
) {
lowerBoundOfOverriddenPropertiesTypes = null
}
}
}
if (lowerBoundOfOverriddenPropertiesTypes != null) {
actions.add(ChangeVariableTypeFix.OnType(property, lowerBoundOfOverriddenPropertiesTypes))
actions.add(OnType(property, lowerBoundOfOverriddenPropertiesTypes))
}
if (overriddenMismatchingProperties.size == 1 && canChangeOverriddenPropertyType) {
val overriddenProperty = DescriptorToSourceUtils.descriptorToDeclaration(overriddenMismatchingProperties.single())
if (overriddenProperty is KtProperty) {
actions.add(ChangeVariableTypeFix.ForOverridden(overriddenProperty, propertyType))
actions.add(ForOverridden(overriddenProperty, propertyType))
}
}
}
@@ -17,9 +17,12 @@
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.descriptors.DescriptorWithRelation
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.EffectiveVisibility.Permissiveness.LESS
import org.jetbrains.kotlin.descriptors.Visibilities.*
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3
import org.jetbrains.kotlin.idea.core.toDescriptor
@@ -32,12 +35,12 @@ import java.util.*
object ChangeVisibilityOnExposureFactory : KotlinIntentionActionsFactory() {
private fun addFixToTargetVisibility(
modifierListOwner: KtModifierListOwner,
descriptor: DeclarationDescriptorWithVisibility,
targetVisibility: Visibility,
boundVisibility: Visibility,
protectedAllowed: Boolean,
fixes: MutableList<IntentionAction>
modifierListOwner: KtModifierListOwner,
descriptor: DeclarationDescriptorWithVisibility,
targetVisibility: Visibility,
boundVisibility: Visibility,
protectedAllowed: Boolean,
fixes: MutableList<IntentionAction>
) {
val possibleVisibilities = when (targetVisibility) {
PROTECTED -> if (protectedAllowed) listOf(boundVisibility, PROTECTED) else listOf(boundVisibility)
@@ -55,7 +58,7 @@ object ChangeVisibilityOnExposureFactory : KotlinIntentionActionsFactory() {
val exposedDiagnostic = factory.cast(diagnostic)
val exposedDescriptor = exposedDiagnostic.b.descriptor as? DeclarationDescriptorWithVisibility ?: return emptyList()
val exposedDeclaration =
DescriptorToSourceUtils.getSourceFromDescriptor(exposedDescriptor) as? KtModifierListOwner ?: return emptyList()
DescriptorToSourceUtils.getSourceFromDescriptor(exposedDescriptor) as? KtModifierListOwner ?: return emptyList()
val exposedVisibility = exposedDiagnostic.c
val userVisibility = exposedDiagnostic.a
val (targetUserVisibility, targetExposedVisibility) = when (exposedVisibility.relation(userVisibility)) {
@@ -67,15 +70,19 @@ object ChangeVisibilityOnExposureFactory : KotlinIntentionActionsFactory() {
val protectedAllowed = exposedDeclaration.parent == userDeclaration?.parent
if (userDeclaration != null) {
val userDescriptor = userDeclaration.toDescriptor() as? DeclarationDescriptorWithVisibility
if (userDescriptor != null && Visibilities.isVisibleIgnoringReceiver(exposedDescriptor, userDescriptor)) {
addFixToTargetVisibility(userDeclaration, userDescriptor,
targetUserVisibility, PRIVATE,
protectedAllowed, result)
if (userDescriptor != null && isVisibleIgnoringReceiver(exposedDescriptor, userDescriptor)) {
addFixToTargetVisibility(
userDeclaration, userDescriptor,
targetUserVisibility, PRIVATE,
protectedAllowed, result
)
}
}
addFixToTargetVisibility(exposedDeclaration, exposedDescriptor,
targetExposedVisibility, PUBLIC,
protectedAllowed, result)
addFixToTargetVisibility(
exposedDeclaration, exposedDescriptor,
targetExposedVisibility, PUBLIC,
protectedAllowed, result
)
return result
}
}
@@ -27,20 +27,20 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents
sealed class CreateLabelFix(
expression: KtLabelReferenceExpression
expression: KtLabelReferenceExpression
) : KotlinQuickFixAction<KtLabelReferenceExpression>(expression) {
class ForLoop(expression: KtLabelReferenceExpression) : CreateLabelFix(expression) {
override val chooserTitle = "Select loop statement to label"
override fun getCandidateExpressions(labelReferenceExpression: KtLabelReferenceExpression) =
labelReferenceExpression.getContainingLoops().toList()
labelReferenceExpression.getContainingLoops().toList()
}
class ForLambda(expression: KtLabelReferenceExpression) : CreateLabelFix(expression) {
override val chooserTitle = "Select lambda to label"
override fun getCandidateExpressions(labelReferenceExpression: KtLabelReferenceExpression) =
labelReferenceExpression.getContainingLambdas().toList()
labelReferenceExpression.getContainingLambdas().toList()
}
override fun getFamilyName() = "Create label"
@@ -70,39 +70,38 @@ sealed class CreateLabelFix(
}
chooseContainerElementIfNecessary(
containers,
editor,
chooserTitle,
true,
{ it },
{
doCreateLabel(expression, it, project)
}
containers,
editor,
chooserTitle,
true,
{ it },
{
doCreateLabel(expression, it, project)
}
)
}
companion object : KotlinSingleIntentionActionFactory() {
private fun KtLabelReferenceExpression.getContainingLoops(): Sequence<KtLoopExpression> {
return parents
.takeWhile { !(it is KtDeclarationWithBody || it is KtClassBody || it is KtFile) }
.filterIsInstance<KtLoopExpression>()
.takeWhile { !(it is KtDeclarationWithBody || it is KtClassBody || it is KtFile) }
.filterIsInstance<KtLoopExpression>()
}
private fun KtLabelReferenceExpression.getContainingLambdas(): Sequence<KtLambdaExpression> {
return parents
.takeWhile { !(it is KtDeclarationWithBody && it !is KtFunctionLiteral || it is KtClassBody || it is KtFile) }
.filterIsInstance<KtLambdaExpression>()
.takeWhile { !(it is KtDeclarationWithBody && it !is KtFunctionLiteral || it is KtClassBody || it is KtFile) }
.filterIsInstance<KtLambdaExpression>()
}
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val labelReferenceExpression = diagnostic.psiElement as? KtLabelReferenceExpression ?: return null
val parentExpression = (labelReferenceExpression.parent as? KtContainerNode)?.parent
return when (parentExpression) {
return when ((labelReferenceExpression.parent as? KtContainerNode)?.parent) {
is KtBreakExpression, is KtContinueExpression -> {
if (labelReferenceExpression.getContainingLoops().any()) CreateLabelFix.ForLoop(labelReferenceExpression) else null
if (labelReferenceExpression.getContainingLoops().any()) ForLoop(labelReferenceExpression) else null
}
is KtReturnExpression -> {
if (labelReferenceExpression.getContainingLambdas().any()) CreateLabelFix.ForLambda(labelReferenceExpression) else null
if (labelReferenceExpression.getContainingLambdas().any()) ForLambda(labelReferenceExpression) else null
}
else -> null
}
@@ -168,7 +168,7 @@ class QuickFixFactoryForTypeMismatchError : KotlinIntentionActionsFactory() {
actions.add(CastExpressionFix(diagnosticElement.getTopMostQualifiedForSelectorIfAny(), expectedType))
}
if (!expectedType.isMarkedNullable && org.jetbrains.kotlin.types.TypeUtils.isNullableType(expressionType)) {
if (!expectedType.isMarkedNullable && TypeUtils.isNullableType(expressionType)) {
val nullableExpected = expectedType.makeNullable()
if (expressionType.isSubtypeOf(nullableExpected)) {
actions.add(AddExclExclCallFix(diagnosticElement.getTopMostQualifiedForSelectorIfAny()))
@@ -21,7 +21,10 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementAsConstructorParameter
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
import org.jetbrains.kotlin.idea.inspections.*
import org.jetbrains.kotlin.idea.inspections.AddModifierFixFactory
import org.jetbrains.kotlin.idea.inspections.InfixCallFixActionFactory
import org.jetbrains.kotlin.idea.inspections.PlatformUnresolvedProvider
import org.jetbrains.kotlin.idea.inspections.RemoveAnnotationFix
import org.jetbrains.kotlin.idea.intentions.AbstractAddAccessorsIntention
import org.jetbrains.kotlin.idea.intentions.AddValVarToConstructorParameterAction
import org.jetbrains.kotlin.idea.intentions.ConvertPropertyInitializerToGetterIntention
@@ -46,7 +49,6 @@ import org.jetbrains.kotlin.idea.quickfix.replaceWith.DeprecatedSymbolUsageFix
import org.jetbrains.kotlin.idea.quickfix.replaceWith.DeprecatedSymbolUsageInWholeProjectFix
import org.jetbrains.kotlin.idea.quickfix.replaceWith.ReplaceProtectedToPublishedApiCallFix
import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
@@ -455,10 +457,10 @@ class QuickFixRegistrar : QuickFixContributor {
NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.registerFactory(ConstFixFactory)
OPERATOR_MODIFIER_REQUIRED.registerFactory(AddModifierFixFactory(KtTokens.OPERATOR_KEYWORD))
OPERATOR_MODIFIER_REQUIRED.registerFactory(AddModifierFixFactory(OPERATOR_KEYWORD))
OPERATOR_MODIFIER_REQUIRED.registerFactory(ImportForMissingOperatorFactory)
INFIX_MODIFIER_REQUIRED.registerFactory(AddModifierFixFactory(KtTokens.INFIX_KEYWORD))
INFIX_MODIFIER_REQUIRED.registerFactory(AddModifierFixFactory(INFIX_KEYWORD))
INFIX_MODIFIER_REQUIRED.registerFactory(InfixCallFixActionFactory)
UNDERSCORE_IS_RESERVED.registerFactory(RenameUnderscoreFix)
@@ -530,7 +532,7 @@ class QuickFixRegistrar : QuickFixContributor {
NO_ACTUAL_FOR_EXPECT.registerFactory(CreateActualFix)
NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS.registerFactory(AddActualFix)
ACTUAL_MISSING.registerFactory(AddModifierFix.createFactory(KtTokens.ACTUAL_KEYWORD))
ACTUAL_MISSING.registerFactory(AddModifierFix.createFactory(ACTUAL_KEYWORD))
CAST_NEVER_SUCCEEDS.registerFactory(ReplacePrimitiveCastWithNumberConversionFix)
@@ -26,8 +26,10 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
class RemoveNullableFix(element: KtNullableType,
private val typeOfError: RemoveNullableFix.NullableKind) : KotlinQuickFixAction<KtNullableType>(element) {
class RemoveNullableFix(
element: KtNullableType,
private val typeOfError: NullableKind
) : KotlinQuickFixAction<KtNullableType>(element) {
enum class NullableKind(val message: String) {
REDUNDANT("Remove redundant '?'"),
SUPERTYPE("Remove '?'"),
@@ -244,7 +244,7 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
receiverType: TypeInfo,
possibleContainers: List<KtElement>
) = super.doCreateCallableInfo(expression, analysisResult, name, receiverType, possibleContainers)?.let {
ByImplicitExtensionReceiver.getCallableWithReceiverInsideExtension(
getCallableWithReceiverInsideExtension(
it,
expression,
analysisResult.bindingContext,
@@ -70,7 +70,7 @@ val ClassKind.actionPriority: IntentionActionPriority
get() = if (this == ANNOTATION_CLASS) IntentionActionPriority.LOW else IntentionActionPriority.NORMAL
data class ClassInfo(
val kind: ClassKind = ClassKind.DEFAULT,
val kind: ClassKind = DEFAULT,
val name: String,
private val targetParents: List<PsiElement>,
val expectedTypeInfo: TypeInfo,
@@ -81,7 +81,7 @@ data class ClassInfo(
) {
val applicableParents by lazy {
targetParents.filter {
if (kind == ClassKind.OBJECT && it is KtClass && (it.isInner() || it.isLocal)) return@filter false
if (kind == OBJECT && it is KtClass && (it.isInner() || it.isLocal)) return@filter false
true
}
}
@@ -124,7 +124,7 @@ open class CreateClassFromUsageFix<E : KtElement> protected constructor(
}
}
if (classInfo.kind != ClassKind.ENUM_ENTRY && parents.find { it is PsiPackage } == null) {
if (classInfo.kind != ENUM_ENTRY && parents.find { it is PsiPackage } == null) {
parents += SeparateFileWrapper(PsiManager.getInstance(project))
}
}
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.quickfix.crossLanguage
import com.intellij.codeInsight.daemon.QuickFixBundle
import com.intellij.lang.jvm.actions.ChangeParametersRequest
import com.intellij.lang.jvm.actions.ExpectedParameter
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
@@ -26,7 +25,10 @@ import org.jetbrains.kotlin.load.java.NOT_NULL_ANNOTATIONS
import org.jetbrains.kotlin.load.java.NULLABLE_ANNOTATIONS
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtParameterList
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
@@ -35,7 +35,10 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations
import org.jetbrains.kotlin.idea.core.getDirectlyOverriddenDeclarations
import org.jetbrains.kotlin.idea.util.*
import org.jetbrains.kotlin.idea.util.actualsForExpected
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
import org.jetbrains.kotlin.idea.util.liftToExpected
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
@@ -47,16 +50,17 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
import java.util.*
abstract class CallableRefactoring<out T: CallableDescriptor>(
val project: Project,
callableDescriptor: T,
val commandName: String) {
abstract class CallableRefactoring<out T : CallableDescriptor>(
val project: Project,
callableDescriptor: T,
val commandName: String
) {
private val LOG = Logger.getInstance(CallableRefactoring::class.java)
@Suppress("UNCHECKED_CAST")
val callableDescriptor = callableDescriptor.liftToExpected() as? T ?: callableDescriptor
private val kind = (callableDescriptor as? CallableMemberDescriptor)?.kind ?: CallableMemberDescriptor.Kind.DECLARATION
private val kind = (callableDescriptor as? CallableMemberDescriptor)?.kind ?: DECLARATION
protected open fun forcePerformForSelectedFunctionOnly(): Boolean {
return false
@@ -76,16 +80,20 @@ abstract class CallableRefactoring<out T: CallableDescriptor>(
}.map { it.liftToExpected() as? CallableDescriptor ?: it }
}
private fun showSuperFunctionWarningDialog(superCallables: Collection<CallableDescriptor>,
callableFromEditor: CallableDescriptor,
options: List<String>): Int {
private fun showSuperFunctionWarningDialog(
superCallables: Collection<CallableDescriptor>,
callableFromEditor: CallableDescriptor,
options: List<String>
): Int {
val superString = superCallables.joinToString(prefix = "\n ", separator = ",\n ", postfix = ".\n\n") {
it.containingDeclaration.name.asString()
}
val message = KotlinBundle.message("x.overrides.y.in.class.list",
DescriptorRenderer.COMPACT.render(callableFromEditor),
superString,
"refactor")
val message = KotlinBundle.message(
"x.overrides.y.in.class.list",
DescriptorRenderer.COMPACT.render(callableFromEditor),
superString,
"refactor"
)
val title = IdeBundle.message("title.warning")!!
val icon = Messages.getQuestionIcon()
return Messages.showDialog(message, title, options.toTypedArray(), 0, icon)
@@ -99,10 +107,9 @@ abstract class CallableRefactoring<out T: CallableDescriptor>(
val unmodifiableFile = element.containingFile?.virtualFile?.presentableUrl
if (unmodifiableFile != null) {
val message = RefactoringBundle.message("refactoring.cannot.be.performed") + "\n" +
IdeBundle.message("error.message.cannot.modify.file.0", unmodifiableFile)
IdeBundle.message("error.message.cannot.modify.file.0", unmodifiableFile)
Messages.showErrorDialog(project, message, CommonBundle.getErrorTitle()!!)
}
else {
} else {
LOG.error("Could not find file for Psi element: " + element.text)
}
@@ -127,14 +134,13 @@ abstract class CallableRefactoring<out T: CallableDescriptor>(
fun buildDialogOptions(isSingleFunctionSelected: Boolean): List<String> {
return if (isSingleFunctionSelected) {
arrayListOf(Messages.YES_BUTTON, Messages.NO_BUTTON, Messages.CANCEL_BUTTON)
}
else {
} else {
arrayListOf(Messages.OK_BUTTON, Messages.CANCEL_BUTTON)
}
}
if (kind == SYNTHESIZED) {
LOG.error("Change signature refactoring should not be called for synthesized member " + callableDescriptor)
LOG.error("Change signature refactoring should not be called for synthesized member $callableDescriptor")
return false
}
@@ -146,7 +152,7 @@ abstract class CallableRefactoring<out T: CallableDescriptor>(
assert(!closestModifiableDescriptors.isEmpty()) { "Should contain original declaration or some of its super declarations" }
val deepestSuperDeclarations =
(callableDescriptor as? CallableMemberDescriptor)?.getDeepestSuperDeclarations()
(callableDescriptor as? CallableMemberDescriptor)?.getDeepestSuperDeclarations()
?: listOf(callableDescriptor)
if (ApplicationManager.getApplication()!!.isUnitTestMode) {
performRefactoring(deepestSuperDeclarations)
@@ -183,11 +189,10 @@ fun getAffectedCallables(project: Project, descriptorsForChange: Collection<Call
return baseCallables + baseCallables.flatMapTo(HashSet<PsiElement>()) { callable ->
if (callable is KtDeclaration && callable.isExpectDeclaration()) {
callable.actualsForExpected()
}
else {
} else {
callable.toLightMethods().flatMap { psiMethod ->
val overrides = OverridingMethodsSearch.search(psiMethod).findAll()
overrides.map { method -> method.namedUnwrappedElement ?: method}
overrides.map { method -> method.namedUnwrappedElement ?: method }
}
}
}
@@ -200,10 +205,8 @@ fun DeclarationDescriptor.getContainingScope(): LexicalScope? {
val lastStatement = block.statements.last()
val bindingContext = lastStatement.analyze()
lastStatement.getResolutionScope(bindingContext, lastStatement.getResolutionFacade())
}
else {
val containingDescriptor = containingDeclaration ?: return null
when (containingDescriptor) {
} else {
when (val containingDescriptor = containingDeclaration ?: return null) {
is ClassDescriptorWithResolutionScopes -> containingDescriptor.scopeForInitializerResolution
is PackageFragmentDescriptor -> LexicalScope.Base(containingDescriptor.getMemberScope().memberScopeAsImportingScope(), this)
else -> null
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaOrKotlinMemberDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.util.javaResolutionFacade
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinMethodDescriptor.Kind
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage
@@ -57,22 +56,26 @@ import org.jetbrains.kotlin.utils.keysToMap
import java.util.*
open class KotlinChangeInfo(
val methodDescriptor: KotlinMethodDescriptor,
private var name: String = methodDescriptor.name,
var newReturnTypeInfo: KotlinTypeInfo = KotlinTypeInfo(true, methodDescriptor.baseDescriptor.returnType),
var newVisibility: Visibility = methodDescriptor.visibility,
parameterInfos: List<KotlinParameterInfo> = methodDescriptor.parameters,
receiver: KotlinParameterInfo? = methodDescriptor.receiver,
val context: PsiElement,
primaryPropagationTargets: Collection<PsiElement> = emptyList()
val methodDescriptor: KotlinMethodDescriptor,
private var name: String = methodDescriptor.name,
var newReturnTypeInfo: KotlinTypeInfo = KotlinTypeInfo(true, methodDescriptor.baseDescriptor.returnType),
var newVisibility: Visibility = methodDescriptor.visibility,
parameterInfos: List<KotlinParameterInfo> = methodDescriptor.parameters,
receiver: KotlinParameterInfo? = methodDescriptor.receiver,
val context: PsiElement,
primaryPropagationTargets: Collection<PsiElement> = emptyList()
) : ChangeInfo, UserDataHolder by UserDataHolderBase() {
private class JvmOverloadSignature(
val method: PsiMethod,
val mandatoryParams: Set<KtParameter>,
val defaultValues: Set<KtExpression>
val method: PsiMethod,
val mandatoryParams: Set<KtParameter>,
val defaultValues: Set<KtExpression>
) {
fun constrainBy(other: JvmOverloadSignature): JvmOverloadSignature {
return JvmOverloadSignature(method, mandatoryParams.intersect(other.mandatoryParams), defaultValues.intersect(other.defaultValues))
return JvmOverloadSignature(
method,
mandatoryParams.intersect(other.mandatoryParams),
defaultValues.intersect(other.defaultValues)
)
}
}
@@ -105,8 +108,8 @@ open class KotlinChangeInfo(
private val isParameterSetOrOrderChangedLazy: Boolean by lazy {
val signatureParameters = getNonReceiverParameters()
methodDescriptor.receiver != receiverParameterInfo ||
signatureParameters.size != methodDescriptor.parametersCount ||
signatureParameters.indices.any { i -> signatureParameters[i].oldIndex != i }
signatureParameters.size != methodDescriptor.parametersCount ||
signatureParameters.indices.any { i -> signatureParameters[i].oldIndex != i }
}
private var isPrimaryMethodUpdated: Boolean = false
@@ -142,11 +145,11 @@ open class KotlinChangeInfo(
newParameters[index] = parameterInfo
}
@JvmOverloads fun addParameter(parameterInfo: KotlinParameterInfo, atIndex: Int = -1) {
@JvmOverloads
fun addParameter(parameterInfo: KotlinParameterInfo, atIndex: Int = -1) {
if (atIndex >= 0) {
newParameters.add(atIndex, parameterInfo)
}
else {
} else {
newParameters.add(parameterInfo)
}
}
@@ -164,7 +167,7 @@ open class KotlinChangeInfo(
}
fun hasParameter(parameterInfo: KotlinParameterInfo): Boolean =
parameterInfo in newParameters
parameterInfo in newParameters
override fun isGenerateDelegate(): Boolean = false
@@ -230,7 +233,7 @@ open class KotlinChangeInfo(
private fun renderReturnTypeIfNeeded(): String? {
val typeInfo = newReturnTypeInfo
if (kind != Kind.FUNCTION) return null
if (typeInfo.type?.isUnit() ?: false) return null
if (typeInfo.type?.isUnit() == true) return null
return typeInfo.render()
}
@@ -244,8 +247,7 @@ open class KotlinChangeInfo(
if (isCustomizedVisibility) {
buffer.append(' ').append(newVisibility).append(" constructor ")
}
}
else {
} else {
if (!DescriptorUtils.isLocal(inheritedCallable.originalCallableDescriptor) && isCustomizedVisibility) {
buffer.append(newVisibility).append(' ')
}
@@ -257,8 +259,7 @@ open class KotlinChangeInfo(
val typeInfo = it.currentTypeInfo
if (typeInfo.type != null && typeInfo.type.isNonExtensionFunctionType) {
buffer.append("(${typeInfo.render()})")
}
else {
} else {
buffer.append(typeInfo.render())
}
buffer.append('.')
@@ -276,7 +277,7 @@ open class KotlinChangeInfo(
fun isRefactoringTarget(inheritedCallableDescriptor: CallableDescriptor?): Boolean {
return inheritedCallableDescriptor != null
&& method == DescriptorToSourceUtils.descriptorToDeclaration(inheritedCallableDescriptor)
&& method == DescriptorToSourceUtils.descriptorToDeclaration(inheritedCallableDescriptor)
}
fun getNewParametersSignature(inheritedCallable: KotlinCallableDefinitionUsage<*>): String {
@@ -284,7 +285,7 @@ open class KotlinChangeInfo(
}
fun getNewParametersSignatureWithoutParentheses(
inheritedCallable: KotlinCallableDefinitionUsage<*>
inheritedCallable: KotlinCallableDefinitionUsage<*>
): String {
val signatureParameters = getNonReceiverParameters()
@@ -322,18 +323,18 @@ open class KotlinChangeInfo(
}
private fun <Parameter> makeSignatures(
parameters: List<Parameter>,
psiMethods: List<PsiMethod>,
getPsi: (Parameter) -> KtParameter,
getDefaultValue: (Parameter) -> KtExpression?
parameters: List<Parameter>,
psiMethods: List<PsiMethod>,
getPsi: (Parameter) -> KtParameter,
getDefaultValue: (Parameter) -> KtExpression?
): List<JvmOverloadSignature> {
val defaultValueCount = parameters.count { getDefaultValue(it) != null }
if (psiMethods.size != defaultValueCount + 1) return emptyList()
val mandatoryParams = parameters.toMutableList()
val defaultValues = ArrayList<KtExpression>()
return psiMethods.map {
JvmOverloadSignature(it, mandatoryParams.asSequence().map(getPsi).toSet(), defaultValues.toSet()).apply {
return psiMethods.map { method ->
JvmOverloadSignature(method, mandatoryParams.asSequence().map(getPsi).toSet(), defaultValues.toSet()).apply {
val param = mandatoryParams.removeLast { getDefaultValue(it) != null } ?: return@apply
defaultValues.add(getDefaultValue(param)!!)
}
@@ -357,8 +358,9 @@ open class KotlinChangeInfo(
fun matchOriginalAndCurrentMethods(currentPsiMethods: List<PsiMethod>): Map<PsiMethod, PsiMethod> {
if (!(isPrimaryMethodUpdated
&& originalBaseFunctionDescriptor is FunctionDescriptor
&& originalBaseFunctionDescriptor.findJvmOverloadsAnnotation() != null)) {
&& originalBaseFunctionDescriptor is FunctionDescriptor
&& originalBaseFunctionDescriptor.findJvmOverloadsAnnotation() != null)
) {
return (originalPsiMethods.zip(currentPsiMethods)).toMap()
}
@@ -384,30 +386,31 @@ open class KotlinChangeInfo(
* So we resort to this hack and pass around "default" type (void) and visibility (package-local)
*/
fun createJavaChangeInfo(originalPsiMethod: PsiMethod,
currentPsiMethod: PsiMethod,
newName: String,
newReturnType: PsiType?,
newParameters: Array<ParameterInfoImpl>
fun createJavaChangeInfo(
originalPsiMethod: PsiMethod,
currentPsiMethod: PsiMethod,
newName: String,
newReturnType: PsiType?,
newParameters: Array<ParameterInfoImpl>
): JavaChangeInfo? {
val newVisibility = if (isPrimaryMethodUpdated)
VisibilityUtil.getVisibilityModifier(currentPsiMethod.modifierList)
else
PsiModifier.PACKAGE_LOCAL
val propagationTargets = primaryPropagationTargets.asSequence()
.mapNotNull { it.getRepresentativeLightMethod() }
.toSet()
.mapNotNull { it.getRepresentativeLightMethod() }
.toSet()
val javaChangeInfo = ChangeSignatureProcessor(
method.project,
originalPsiMethod,
false,
newVisibility,
newName,
CanonicalTypes.createTypeWrapper(newReturnType ?: PsiType.VOID),
newParameters,
arrayOf<ThrownExceptionInfo>(),
propagationTargets,
emptySet()
method.project,
originalPsiMethod,
false,
newVisibility,
newName,
CanonicalTypes.createTypeWrapper(newReturnType ?: PsiType.VOID),
newParameters,
arrayOf<ThrownExceptionInfo>(),
propagationTargets,
emptySet()
).changeInfo
javaChangeInfo.updateMethod(currentPsiMethod)
@@ -415,9 +418,9 @@ open class KotlinChangeInfo(
}
fun getJavaParameterInfos(
originalPsiMethod: PsiMethod,
currentPsiMethod: PsiMethod,
newParameterList: List<KotlinParameterInfo>
originalPsiMethod: PsiMethod,
currentPsiMethod: PsiMethod,
newParameterList: List<KotlinParameterInfo>
): MutableList<ParameterInfoImpl> {
val defaultValuesToSkip = newParameterList.size - currentPsiMethod.parameterList.parametersCount
val defaultValuesToRetain = newParameterList.count { it.defaultValueForParameter != null } - defaultValuesToSkip
@@ -427,41 +430,42 @@ open class KotlinChangeInfo(
var defaultValuesRemained = defaultValuesToRetain
for (param in newParameterList) {
if (param.isNewParameter || param.defaultValueForParameter == null || defaultValuesRemained-- > 0) continue
newParameterList.asSequence().withIndex().filter { it.value.oldIndex >= param.oldIndex }.toList().forEach { oldIndices[it.index]-- }
newParameterList.asSequence().withIndex().filter { it.value.oldIndex >= param.oldIndex }.toList()
.forEach { oldIndices[it.index]-- }
}
defaultValuesRemained = defaultValuesToRetain
val oldParameterCount = originalPsiMethod.parameterList.parametersCount
var indexInCurrentPsiMethod = 0
return newParameterList.asSequence().withIndex()
.mapNotNullTo(ArrayList()) map@ { pair ->
val (i, info) = pair
.mapNotNullTo(ArrayList()) map@{ pair ->
val (i, info) = pair
if (info.defaultValueForParameter != null && defaultValuesRemained-- <= 0) return@map null
if (info.defaultValueForParameter != null && defaultValuesRemained-- <= 0) return@map null
val oldIndex = oldIndices[i]
val javaOldIndex = when {
methodDescriptor.receiver == null -> oldIndex
info == methodDescriptor.receiver -> 0
oldIndex >= 0 -> oldIndex + 1
else -> -1
}
if (javaOldIndex >= oldParameterCount) return@map null
val type = if (isPrimaryMethodUpdated)
currentPsiMethod.parameterList.parameters[indexInCurrentPsiMethod++].type
else
PsiType.VOID
val defaultValue = info.defaultValueForCall ?: info.defaultValueForParameter
ParameterInfoImpl(javaOldIndex, info.name, type, defaultValue?.text ?: "")
val oldIndex = oldIndices[i]
val javaOldIndex = when {
methodDescriptor.receiver == null -> oldIndex
info == methodDescriptor.receiver -> 0
oldIndex >= 0 -> oldIndex + 1
else -> -1
}
if (javaOldIndex >= oldParameterCount) return@map null
val type = if (isPrimaryMethodUpdated)
currentPsiMethod.parameterList.parameters[indexInCurrentPsiMethod++].type
else
PsiType.VOID
val defaultValue = info.defaultValueForCall ?: info.defaultValueForParameter
ParameterInfoImpl(javaOldIndex, info.name, type, defaultValue?.text ?: "")
}
}
fun createJavaChangeInfoForFunctionOrGetter(
originalPsiMethod: PsiMethod,
currentPsiMethod: PsiMethod,
isGetter: Boolean
originalPsiMethod: PsiMethod,
currentPsiMethod: PsiMethod,
isGetter: Boolean
): JavaChangeInfo? {
val newParameterList = listOfNotNull(receiverParameterInfo) + getNonReceiverParameters()
val newJavaParameters = getJavaParameterInfos(originalPsiMethod, currentPsiMethod, newParameterList).toTypedArray()
@@ -476,8 +480,7 @@ open class KotlinChangeInfo(
val newIndex = if (receiverParameterInfo != null) 1 else 0
val setterParameter = currentPsiMethod.parameterList.parameters[newIndex]
newJavaParameters.add(ParameterInfoImpl(oldIndex, setterParameter.name, setterParameter.type))
}
else {
} else {
newJavaParameters.add(ParameterInfoImpl(oldIndex, "receiver", PsiType.VOID))
}
@@ -526,8 +529,8 @@ val KotlinChangeInfo.oldName: String?
fun KotlinChangeInfo.getAffectedCallables(): Collection<UsageInfo> = methodDescriptor.affectedCallables + propagationTargetUsageInfos
fun ChangeInfo.toJetChangeInfo(
originalChangeSignatureDescriptor: KotlinMethodDescriptor,
resolutionFacade: ResolutionFacade
originalChangeSignatureDescriptor: KotlinMethodDescriptor,
resolutionFacade: ResolutionFacade
): KotlinChangeInfo {
val method = method as PsiMethod
@@ -544,34 +547,38 @@ fun ChangeInfo.toJetChangeInfo(
val defaultValueText = info.defaultValue
val defaultValueExpr =
when {
info is KotlinAwareJavaParameterInfoImpl -> info.kotlinDefaultValue
language.`is`(JavaLanguage.INSTANCE) && !defaultValueText.isNullOrEmpty() -> {
PsiElementFactory.SERVICE.getInstance(method.project)
.createExpressionFromText(defaultValueText!!, null)
.j2k()
}
else -> null
when {
info is KotlinAwareJavaParameterInfoImpl -> info.kotlinDefaultValue
language.`is`(JavaLanguage.INSTANCE) && !defaultValueText.isNullOrEmpty() -> {
PsiElementFactory.SERVICE.getInstance(method.project)
.createExpressionFromText(defaultValueText, null)
.j2k()
}
else -> null
}
val parameterType = if (oldIndex >= 0) originalParameterDescriptors[oldIndex].type else currentType
val originalKtParameter = originalParameterDescriptors.getOrNull(oldIndex)?.source?.getPsi() as? KtParameter
val valOrVar = originalKtParameter?.valOrVarKeyword?.toValVar() ?: KotlinValVar.None
KotlinParameterInfo(callableDescriptor = functionDescriptor,
originalIndex = oldIndex,
name = info.name,
originalTypeInfo = KotlinTypeInfo(false, parameterType),
defaultValueForCall = defaultValueExpr,
valOrVar = valOrVar).apply {
KotlinParameterInfo(
callableDescriptor = functionDescriptor,
originalIndex = oldIndex,
name = info.name,
originalTypeInfo = KotlinTypeInfo(false, parameterType),
defaultValueForCall = defaultValueExpr,
valOrVar = valOrVar
).apply {
currentTypeInfo = KotlinTypeInfo(false, currentType)
}
}
return KotlinChangeInfo(originalChangeSignatureDescriptor,
newName,
KotlinTypeInfo(true, functionDescriptor.returnType),
functionDescriptor.visibility,
newParameters,
null,
method)
return KotlinChangeInfo(
originalChangeSignatureDescriptor,
newName,
KotlinTypeInfo(true, functionDescriptor.returnType),
functionDescriptor.visibility,
newParameters,
null,
method
)
}
@@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiElement
import com.intellij.refactoring.BaseRefactoringProcessor
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessorBase
import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor
@@ -38,9 +37,9 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinWrappe
import java.util.*
class KotlinChangeSignatureProcessor(
project: Project,
changeInfo: KotlinChangeInfo,
private val commandName: String
project: Project,
changeInfo: KotlinChangeInfo,
private val commandName: String
) : ChangeSignatureProcessorBase(project, KotlinChangeInfoWrapper(changeInfo)) {
val ktChangeInfo
get() = changeInfo.delegate!!
@@ -80,7 +79,7 @@ class KotlinChangeSignatureProcessor(
if (!usageProcessors.all { it.setupDefaultValues(myChangeInfo, refUsages, myProject) }) return false
val conflictDescriptions = object: MultiMap<PsiElement, String>() {
val conflictDescriptions = object : MultiMap<PsiElement, String>() {
override fun createCollection() = LinkedHashSet<String>()
}
usageProcessors.forEach { conflictDescriptions.putAllValues(it.findConflicts(myChangeInfo, refUsages)) }
@@ -92,7 +91,7 @@ class KotlinChangeSignatureProcessor(
RenameUtil.removeConflictUsages(usagesSet)
if (!conflictDescriptions.isEmpty) {
if (ApplicationManager.getApplication().isUnitTestMode) {
throw BaseRefactoringProcessor.ConflictsInTestsException(conflictDescriptions.values())
throw ConflictsInTestsException(conflictDescriptions.values())
}
val dialog = prepareConflictsDialog(conflictDescriptions, usages)
@@ -127,8 +126,7 @@ class KotlinChangeSignatureProcessor(
override fun performRefactoring(usages: Array<out UsageInfo>) {
try {
super.performRefactoring(usages)
}
finally {
} finally {
changeInfo.invalidate()
}
}
@@ -65,10 +65,10 @@ import java.util.*
import javax.swing.*
class KotlinChangeSignatureDialog(
project: Project,
methodDescriptor: KotlinMethodDescriptor,
context: PsiElement,
private val commandName: String?
project: Project,
methodDescriptor: KotlinMethodDescriptor,
context: PsiElement,
private val commandName: String?
) : ChangeSignatureDialogBase<
KotlinParameterInfo,
PsiElement,
@@ -76,15 +76,20 @@ class KotlinChangeSignatureDialog(
KotlinMethodDescriptor,
ParameterTableModelItemBase<KotlinParameterInfo>,
KotlinCallableParameterTableModel>(project, methodDescriptor, false, context) {
override fun getFileType() = KotlinFileType.INSTANCE
override fun getFileType(): KotlinFileType = KotlinFileType.INSTANCE
override fun createParametersInfoModel(descriptor: KotlinMethodDescriptor) = createParametersInfoModel(descriptor, myDefaultValueContext)
override fun createParametersInfoModel(descriptor: KotlinMethodDescriptor) =
createParametersInfoModel(descriptor, myDefaultValueContext)
override fun createReturnTypeCodeFragment() = createReturnTypeCodeFragment(myProject, myMethod)
private val parametersTableModel: KotlinCallableParameterTableModel get() = super.myParametersTableModel
override fun getRowPresentation(item: ParameterTableModelItemBase<KotlinParameterInfo>, selected: Boolean, focused: Boolean): JComponent? {
override fun getRowPresentation(
item: ParameterTableModelItemBase<KotlinParameterInfo>,
selected: Boolean,
focused: Boolean
): JComponent? {
val panel = JPanel(BorderLayout())
val valOrVar = if (myMethod.kind === Kind.PRIMARY_CONSTRUCTOR) {
@@ -93,8 +98,7 @@ class KotlinChangeSignatureDialog(
KotlinValVar.Val -> "val "
KotlinValVar.Var -> "var "
}
}
else {
} else {
""
}
@@ -112,14 +116,13 @@ class KotlinChangeSignatureDialog(
override fun shouldHaveBorder() = false
}
val plainFont = EditorColorsManager.getInstance().globalScheme.getFont(EditorFontType.PLAIN)
val plainFont = EditorColorsManager.getInstance().globalScheme.getFont(EditorFontType.PLAIN)
field.font = Font(plainFont.fontName, plainFont.style, 12)
if (selected && focused) {
panel.background = UIUtil.getTableSelectionBackground()
field.setAsRendererWithSelection(UIUtil.getTableSelectionBackground(), UIUtil.getTableSelectionForeground())
}
else {
} else {
panel.background = UIUtil.getTableBackground()
if (selected && !focused) {
panel.border = DottedBorder(UIUtil.getTableForeground())
@@ -136,7 +139,7 @@ class KotlinChangeSignatureDialog(
}
private fun getColumnTextMaxLength(nameFunction: Function1<ParameterTableModelItemBase<KotlinParameterInfo>, String?>) =
parametersTableModel.items.asSequence().map { nameFunction(it)?.length ?: 0 }.max() ?: 0
parametersTableModel.items.asSequence().map { nameFunction(it)?.length ?: 0 }.max() ?: 0
private fun getParamNamesMaxLength() = getColumnTextMaxLength { getPresentationName(it) }
@@ -147,17 +150,17 @@ class KotlinChangeSignatureDialog(
override fun isListTableViewSupported() = true
override fun isEmptyRow(row: ParameterTableModelItemBase<KotlinParameterInfo>): Boolean {
if (!row.parameter.name.isEmpty()) return false
if (!row.parameter.typeText.isEmpty()) return false
if (row.parameter.name.isNotEmpty()) return false
if (row.parameter.typeText.isNotEmpty()) return false
return true
}
override fun createCallerChooser(title: String, treeToReuse: Tree?, callback: Consumer<Set<PsiElement>>) =
KotlinCallerChooser(myMethod.method, myProject, title, treeToReuse, callback)
KotlinCallerChooser(myMethod.method, myProject, title, treeToReuse, callback)
// Forbid receiver propagation
override fun mayPropagateParameters() =
parameters.any { it.isNewParameter && it != parametersTableModel.receiver }
parameters.any { it.isNewParameter && it != parametersTableModel.receiver }
override fun getTableEditor(table: JTable, item: ParameterTableModelItemBase<KotlinParameterInfo>): JBTableRowEditor? {
return object : JBTableRowEditor() {
@@ -169,7 +172,7 @@ class KotlinChangeSignatureDialog(
}
private fun isDefaultColumnEnabled() =
item.parameter.isNewParameter && item.parameter != myMethod.receiver
item.parameter.isNewParameter && item.parameter != myMethod.receiver
override fun prepareEditor(table: JTable, row: Int) {
layout = BoxLayout(this, BoxLayout.X_AXIS)
@@ -185,18 +188,15 @@ class KotlinChangeSignatureDialog(
val document = PsiDocumentManager.getInstance(project).getDocument(item.typeCodeFragment)
editor = EditorTextField(document, project, fileType)
component = editor
}
else if (KotlinCallableParameterTableModel.isNameColumn(columnInfo)) {
} else if (KotlinCallableParameterTableModel.isNameColumn(columnInfo)) {
editor = nameEditor
component = editor
updateNameEditor()
}
else if (KotlinCallableParameterTableModel.isDefaultValueColumn(columnInfo) && isDefaultColumnEnabled()) {
} else if (KotlinCallableParameterTableModel.isDefaultValueColumn(columnInfo) && isDefaultColumnEnabled()) {
val document = PsiDocumentManager.getInstance(project).getDocument(item.defaultValueCodeFragment)
editor = EditorTextField(document, project, fileType)
component = editor
}
else if (KotlinPrimaryConstructorParameterTableModel.isValVarColumn(columnInfo)) {
} else if (KotlinPrimaryConstructorParameterTableModel.isValVarColumn(columnInfo)) {
val comboBox = JComboBox(KotlinValVar.values())
comboBox.selectedItem = item.parameter.valOrVar
comboBox.addItemListener {
@@ -205,8 +205,7 @@ class KotlinChangeSignatureDialog(
}
component = comboBox
editor = null
}
else if (KotlinFunctionParameterTableModel.isReceiverColumn(columnInfo)) {
} else if (KotlinFunctionParameterTableModel.isReceiverColumn(columnInfo)) {
val checkBox = JCheckBox()
checkBox.isSelected = parametersTableModel.receiver == item.parameter
checkBox.addItemListener {
@@ -217,8 +216,7 @@ class KotlinChangeSignatureDialog(
}
component = checkBox
editor = null
}
else
} else
continue
val label = JBLabel(columnInfo.name, UIUtil.ComponentStyle.SMALL)
@@ -226,11 +224,11 @@ class KotlinChangeSignatureDialog(
if (editor != null) {
editor.addDocumentListener(
object : DocumentListener {
override fun documentChanged(e: DocumentEvent) {
fireDocumentChanged(e, columnFinal)
}
object : DocumentListener {
override fun documentChanged(e: DocumentEvent) {
fireDocumentChanged(e, columnFinal)
}
}
)
editor.setPreferredWidth(table.width / parametersTableModel.columnCount)
}
@@ -277,7 +275,7 @@ class KotlinChangeSignatureDialog(
intArrayOf(4, getParamNamesMaxLength(), getTypesMaxLength())
var columnIndex = 0
for (i in (if (myMethod.kind === Kind.PRIMARY_CONSTRUCTOR) 0 else 1)..columnLetters.size - 1) {
for (i in (if (myMethod.kind === Kind.PRIMARY_CONSTRUCTOR) 0 else 1) until columnLetters.size) {
val width = getColumnWidth(columnLetters[i])
if (x <= width)
@@ -311,18 +309,20 @@ class KotlinChangeSignatureDialog(
}
override fun calculateSignature(): String {
val changeInfo = evaluateChangeInfo(parametersTableModel,
myReturnTypeCodeFragment,
getMethodDescriptor(),
visibility,
methodName,
myDefaultValueContext,
true)
val changeInfo = evaluateChangeInfo(
parametersTableModel,
myReturnTypeCodeFragment,
getMethodDescriptor(),
visibility,
methodName,
myDefaultValueContext,
true
)
return changeInfo.getNewSignature(getMethodDescriptor().originalPrimaryCallable)
}
override fun createVisibilityControl() = ComboBoxVisibilityPanel(
arrayOf(Visibilities.INTERNAL, Visibilities.PRIVATE, Visibilities.PROTECTED, Visibilities.PUBLIC)
arrayOf(Visibilities.INTERNAL, Visibilities.PRIVATE, Visibilities.PROTECTED, Visibilities.PUBLIC)
)
override fun updateSignatureAlarmFired() {
@@ -332,27 +332,30 @@ class KotlinChangeSignatureDialog(
override fun validateAndCommitData(): String? {
if (myMethod.canChangeReturnType() == MethodDescriptor.ReadWriteOption.ReadWrite &&
myReturnTypeCodeFragment.getTypeInfo(true, false).type == null) {
myReturnTypeCodeFragment.getTypeInfo(isCovariant = true, forPreview = false).type == null
) {
if (Messages.showOkCancelDialog(
myProject,
"Return type '${myReturnTypeCodeFragment!!.text}' cannot be resolved.\nContinue?",
RefactoringBundle.message("changeSignature.refactoring.name"),
Messages.getWarningIcon()
) != Messages.OK) {
return ChangeSignatureDialogBase.EXIT_SILENTLY
) != Messages.OK
) {
return EXIT_SILENTLY
}
}
for (item in parametersTableModel.items) {
if (item.typeCodeFragment.getTypeInfo(true, false).type == null) {
if (item.typeCodeFragment.getTypeInfo(isCovariant = true, forPreview = false).type == null) {
val paramText = if (item.parameter != parametersTableModel.receiver) "parameter '${item.parameter.name}'" else "receiver"
if (Messages.showOkCancelDialog(
myProject,
"Type '${item.typeCodeFragment.text}' for $paramText cannot be resolved.\nContinue?",
RefactoringBundle.message("changeSignature.refactoring.name"),
Messages.getWarningIcon()
) != Messages.OK) {
return ChangeSignatureDialogBase.EXIT_SILENTLY
) != Messages.OK
) {
return EXIT_SILENTLY
}
}
}
@@ -366,7 +369,7 @@ class KotlinChangeSignatureDialog(
if (myMethod.canChangeReturnType() === MethodDescriptor.ReadWriteOption.ReadWrite) {
(myReturnTypeCodeFragment as? KtTypeCodeFragment)
?.validateElement(KotlinRefactoringBundle.message("return.type.is.invalid"))
?.validateElement(KotlinRefactoringBundle.message("return.type.is.invalid"))
}
for (item in parametersTableModel.items) {
@@ -377,18 +380,20 @@ class KotlinChangeSignatureDialog(
}
(item.typeCodeFragment as? KtTypeCodeFragment)
?.validateElement(KotlinRefactoringBundle.message("parameter.type.is.invalid", item.typeCodeFragment.text))
?.validateElement(KotlinRefactoringBundle.message("parameter.type.is.invalid", item.typeCodeFragment.text))
}
}
override fun createRefactoringProcessor(): BaseRefactoringProcessor {
val changeInfo = evaluateChangeInfo(parametersTableModel,
myReturnTypeCodeFragment,
getMethodDescriptor(),
visibility,
methodName,
myDefaultValueContext,
false)
val changeInfo = evaluateChangeInfo(
parametersTableModel,
myReturnTypeCodeFragment,
getMethodDescriptor(),
visibility,
methodName,
myDefaultValueContext,
false
)
changeInfo.primaryPropagationTargets = myMethodsToPropagateParameters ?: emptyList()
return KotlinChangeSignatureProcessor(myProject, changeInfo, commandName ?: title)
}
@@ -397,16 +402,19 @@ class KotlinChangeSignatureDialog(
override fun getSelectedIdx(): Int {
return myMethod.parameters.withIndex().firstOrNull { it.value.isNewParameter }?.index
?: super.getSelectedIdx()
?: super.getSelectedIdx()
}
companion object {
private fun createParametersInfoModel(descriptor: KotlinMethodDescriptor, defaultValueContext: PsiElement): KotlinCallableParameterTableModel {
private fun createParametersInfoModel(
descriptor: KotlinMethodDescriptor,
defaultValueContext: PsiElement
): KotlinCallableParameterTableModel {
val typeContext = getTypeCodeFragmentContext(descriptor.baseDeclaration)
return when (descriptor.kind) {
KotlinMethodDescriptor.Kind.FUNCTION -> KotlinFunctionParameterTableModel(descriptor, typeContext, defaultValueContext)
KotlinMethodDescriptor.Kind.PRIMARY_CONSTRUCTOR -> KotlinPrimaryConstructorParameterTableModel(descriptor, typeContext, defaultValueContext)
KotlinMethodDescriptor.Kind.SECONDARY_CONSTRUCTOR -> KotlinSecondaryConstructorParameterTableModel(descriptor, typeContext, defaultValueContext)
Kind.FUNCTION -> KotlinFunctionParameterTableModel(descriptor, typeContext, defaultValueContext)
Kind.PRIMARY_CONSTRUCTOR -> KotlinPrimaryConstructorParameterTableModel(descriptor, typeContext, defaultValueContext)
Kind.SECONDARY_CONSTRUCTOR -> KotlinSecondaryConstructorParameterTableModel(descriptor, typeContext, defaultValueContext)
}
}
@@ -425,21 +433,25 @@ class KotlinChangeSignatureDialog(
}
private fun createReturnTypeCodeFragment(project: Project, method: KotlinMethodDescriptor) =
KtPsiFactory(project).createTypeCodeFragment(method.returnTypeInfo.render(), getTypeCodeFragmentContext(method.baseDeclaration))
KtPsiFactory(project).createTypeCodeFragment(method.returnTypeInfo.render(), getTypeCodeFragmentContext(method.baseDeclaration))
fun createRefactoringProcessorForSilentChangeSignature(project: Project,
commandName: String,
method: KotlinMethodDescriptor,
defaultValueContext: PsiElement): BaseRefactoringProcessor {
fun createRefactoringProcessorForSilentChangeSignature(
project: Project,
commandName: String,
method: KotlinMethodDescriptor,
defaultValueContext: PsiElement
): BaseRefactoringProcessor {
val parameterTableModel = createParametersInfoModel(method, defaultValueContext)
parameterTableModel.setParameterInfos(method.parameters)
val changeInfo = evaluateChangeInfo(parameterTableModel,
createReturnTypeCodeFragment(project, method),
method,
method.visibility,
method.name,
defaultValueContext,
false)
val changeInfo = evaluateChangeInfo(
parameterTableModel,
createReturnTypeCodeFragment(project, method),
method,
method.visibility,
method.name,
defaultValueContext,
false
)
return KotlinChangeSignatureProcessor(project, changeInfo, commandName)
}
@@ -455,13 +467,15 @@ class KotlinChangeSignatureDialog(
}
}
private fun evaluateChangeInfo(parametersModel: KotlinCallableParameterTableModel,
returnTypeCodeFragment: PsiCodeFragment?,
methodDescriptor: KotlinMethodDescriptor,
visibility: Visibility?,
methodName: String,
defaultValueContext: PsiElement,
forPreview: Boolean): KotlinChangeInfo {
private fun evaluateChangeInfo(
parametersModel: KotlinCallableParameterTableModel,
returnTypeCodeFragment: PsiCodeFragment?,
methodDescriptor: KotlinMethodDescriptor,
visibility: Visibility?,
methodName: String,
defaultValueContext: PsiElement,
forPreview: Boolean
): KotlinChangeInfo {
val parameters = parametersModel.items.map { parameter ->
val parameterInfo = parameter.parameter
@@ -476,13 +490,15 @@ class KotlinChangeSignatureDialog(
parameterInfo
}
return KotlinChangeInfo(methodDescriptor.original,
methodName,
returnTypeCodeFragment.getTypeInfo(true, forPreview),
visibility ?: Visibilities.DEFAULT_VISIBILITY,
parameters,
parametersModel.receiver,
defaultValueContext)
return KotlinChangeInfo(
methodDescriptor.original,
methodName,
returnTypeCodeFragment.getTypeInfo(true, forPreview),
visibility ?: Visibilities.DEFAULT_VISIBILITY,
parameters,
parametersModel.receiver,
defaultValueContext
)
}
}
}
@@ -131,7 +131,7 @@ class KotlinCallableDefinitionUsage<T : PsiElement>(
val receiverTypeText = changeInfo.renderReceiverType(this)
val receiverTypeRef = if (receiverTypeText != null) psiFactory.createType(receiverTypeText) else null
val newReceiverTypeRef = element.setReceiverTypeReference(receiverTypeRef)
newReceiverTypeRef?.addToShorteningWaitSet(ShortenReferences.Options.DEFAULT)
newReceiverTypeRef?.addToShorteningWaitSet(Options.DEFAULT)
}
if (changeInfo.isVisibilityChanged() && !KtPsiUtil.isLocal(element as KtDeclaration)) {
@@ -25,6 +25,7 @@ import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeInfo
@@ -33,7 +34,6 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.isInsideOfCallerBod
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.createNameCounterpartMap
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler
import org.jetbrains.kotlin.idea.refactoring.replaceListPsiAndKeepDelimiters
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.name.Name
@@ -55,9 +55,9 @@ import org.jetbrains.kotlin.utils.sure
import java.util.*
class KotlinFunctionCallUsage(
element: KtCallElement,
private val callee: KotlinCallableDefinitionUsage<*>,
forcedResolvedCall: ResolvedCall<*>? = null
element: KtCallElement,
private val callee: KotlinCallableDefinitionUsage<*>,
forcedResolvedCall: ResolvedCall<*>? = null
) : KotlinUsageInfo<KtCallElement>(element) {
private val context = element.analyze(BodyResolveMode.FULL)
private val resolvedCall = forcedResolvedCall ?: element.getResolvedCall(context)
@@ -78,8 +78,7 @@ class KotlinFunctionCallUsage(
if (element.valueArgumentList != null) {
if (changeInfo.isParameterSetOrOrderChanged) {
result = updateArgumentsAndReceiver(changeInfo, element, allUsages)
}
else {
} else {
changeArgumentNames(changeInfo, element)
}
}
@@ -105,10 +104,10 @@ class KotlinFunctionCallUsage(
if (skipUnmatchedArgumentsCheck) return false
if (!resolvedCall.call.valueArguments.all{ resolvedCall.getArgumentMapping(it) is ArgumentMatch }) return true
if (!resolvedCall.call.valueArguments.all { resolvedCall.getArgumentMapping(it) is ArgumentMatch }) return true
val arguments = resolvedCall.valueArguments
return !resolvedCall.resultingDescriptor.valueParameters.all{ arguments.containsKey(it) }
return !resolvedCall.resultingDescriptor.valueParameters.all { arguments.containsKey(it) }
}
private val isPropertyJavaUsage: Boolean
@@ -121,8 +120,7 @@ class KotlinFunctionCallUsage(
private fun changeNameIfNeeded(changeInfo: KotlinChangeInfo, element: KtCallElement) {
if (!changeInfo.isNameChanged) return
val callee = element.calleeExpression
if (callee !is KtSimpleNameExpression) return
val callee = element.calleeExpression as? KtSimpleNameExpression ?: return
var newName = changeInfo.newName
if (isPropertyJavaUsage) {
@@ -136,9 +134,9 @@ class KotlinFunctionCallUsage(
}
private fun getReceiverExpressionIfMatched(
receiverValue: ReceiverValue?,
originalDescriptor: DeclarationDescriptor,
psiFactory: KtPsiFactory
receiverValue: ReceiverValue?,
originalDescriptor: DeclarationDescriptor,
psiFactory: KtPsiFactory
): KtExpression? {
if (receiverValue == null) return null
@@ -146,8 +144,7 @@ class KotlinFunctionCallUsage(
// to simplify checking against receiver value in the corresponding resolved call
val adjustedDescriptor = if (originalDescriptor is CallableDescriptor && originalDescriptor !is ReceiverParameterDescriptor) {
originalDescriptor.extensionReceiverParameter ?: return null
}
else originalDescriptor
} else originalDescriptor
val currentIsExtension = resolvedCall!!.extensionReceiver == receiverValue
val originalIsExtension = adjustedDescriptor is ReceiverParameterDescriptor && adjustedDescriptor.value is ExtensionReceiver
@@ -174,9 +171,9 @@ class KotlinFunctionCallUsage(
}
private fun substituteReferences(
expression: KtExpression,
referenceMap: Map<PsiReference, DeclarationDescriptor>,
psiFactory: KtPsiFactory
expression: KtExpression,
referenceMap: Map<PsiReference, DeclarationDescriptor>,
psiFactory: KtPsiFactory
): KtExpression {
if (referenceMap.isEmpty() || resolvedCall == null) return expression
@@ -199,28 +196,30 @@ class KotlinFunctionCallUsage(
addReceiver = false
argumentExpression = argument.getArgumentExpression()
}
else {
} else {
addReceiver = descriptor !is ReceiverParameterDescriptor
argumentExpression =
getReceiverExpressionIfMatched(resolvedCall.extensionReceiver, descriptor, psiFactory)
getReceiverExpressionIfMatched(resolvedCall.extensionReceiver, descriptor, psiFactory)
?: getReceiverExpressionIfMatched(resolvedCall.dispatchReceiver, descriptor, psiFactory)
}
if (argumentExpression == null) continue
if (needSeparateVariable(argumentExpression)
&& PsiTreeUtil.getNonStrictParentOfType(element,
KtConstructorDelegationCall::class.java,
KtSuperTypeListEntry::class.java,
KtParameter::class.java) == null) {
&& PsiTreeUtil.getNonStrictParentOfType(
element,
KtConstructorDelegationCall::class.java,
KtSuperTypeListEntry::class.java,
KtParameter::class.java
) == null
) {
KotlinIntroduceVariableHandler.doRefactoring(
project, null, argumentExpression,
isVar = false,
occurrencesToReplace = listOf(argumentExpression),
onNonInteractiveFinish = {
argumentExpression = psiFactory.createExpression(it.name!!)
})
project, null, argumentExpression,
isVar = false,
occurrencesToReplace = listOf(argumentExpression),
onNonInteractiveFinish = {
argumentExpression = psiFactory.createExpression(it.name!!)
})
}
var expressionToReplace: KtExpression = nameCounterpartMap[ref.element] ?: continue
@@ -239,8 +238,7 @@ class KotlinFunctionCallUsage(
val replacement = psiFactory.createExpression("${argumentExpression!!.text}.${expressionToReplace.text}")
replacements.add(expressionToReplace to replacement)
}
else {
} else {
replacements.add(expressionToReplace to argumentExpression!!)
}
}
@@ -258,10 +256,10 @@ class KotlinFunctionCallUsage(
}
class ArgumentInfo(
val parameter: KotlinParameterInfo,
val parameterIndex: Int,
val resolvedArgument: ResolvedValueArgument?,
val receiverValue: ReceiverValue?
val parameter: KotlinParameterInfo,
val parameterIndex: Int,
val resolvedArgument: ResolvedValueArgument?,
val receiverValue: ReceiverValue?
) {
private val mainValueArgument: ValueArgument?
get() = resolvedArgument?.arguments?.firstOrNull()
@@ -290,9 +288,9 @@ class KotlinFunctionCallUsage(
by NotNullablePsiCopyableUserDataProperty(Key.create("GENERATED_ARGUMENT_VALUE"), false)
private fun ArgumentInfo.getArgumentByDefaultValue(
element: KtCallElement,
allUsages: Array<out UsageInfo>,
psiFactory: KtPsiFactory
element: KtCallElement,
allUsages: Array<out UsageInfo>,
psiFactory: KtPsiFactory
): KtValueArgument {
val isInsideOfCallerBody = element.isInsideOfCallerBody(allUsages)
val defaultValueForCall = parameter.defaultValueForCall
@@ -311,12 +309,16 @@ class KotlinFunctionCallUsage(
}
private fun ExpressionReceiver.wrapInvalidated(element: KtCallElement): ExpressionReceiver {
return object: ExpressionReceiver by this {
return object : ExpressionReceiver by this {
override val expression = element.getQualifiedExpressionForSelector()!!.receiverExpression
}
}
private fun updateArgumentsAndReceiver(changeInfo: KotlinChangeInfo, element: KtCallElement, allUsages: Array<out UsageInfo>): KtElement {
private fun updateArgumentsAndReceiver(
changeInfo: KotlinChangeInfo,
element: KtCallElement,
allUsages: Array<out UsageInfo>
): KtElement {
if (isPropertyJavaUsage) return updateJavaPropertyCall(changeInfo, element)
val fullCallElement = element.getQualifiedExpressionForSelector() ?: element
@@ -351,17 +353,17 @@ class KotlinFunctionCallUsage(
val lastParameterIndex = newParameters.lastIndex
var firstNamedIndex = newArgumentInfos.firstOrNull {
it.wasNamed
|| (it.parameter.isNewParameter && purelyNamedCall)
|| (it.resolvedArgument is VarargValueArgument && it.parameterIndex < lastParameterIndex)
|| (it.parameter.isNewParameter && purelyNamedCall)
|| (it.resolvedArgument is VarargValueArgument && it.parameterIndex < lastParameterIndex)
}?.parameterIndex
if (firstNamedIndex == null) {
val lastNonDefaultArgIndex = (lastParameterIndex downTo 0).firstOrNull { !newArgumentInfos[it].shouldSkip() }
?: -1
?: -1
firstNamedIndex = (0..lastNonDefaultArgIndex).firstOrNull { newArgumentInfos[it].shouldSkip() }
}
val lastPositionalIndex = if (firstNamedIndex != null) firstNamedIndex - 1 else lastParameterIndex
(lastPositionalIndex + 1 .. lastParameterIndex).forEach { newArgumentInfos[it].makeNamed(callee) }
(lastPositionalIndex + 1..lastParameterIndex).forEach { newArgumentInfos[it].makeNamed(callee) }
val psiFactory = KtPsiFactory(element.project)
@@ -377,8 +379,7 @@ class KotlinFunctionCallUsage(
continue
}
val resolvedArgument = argInfo.resolvedArgument
when (resolvedArgument) {
when (val resolvedArgument = argInfo.resolvedArgument) {
null, is DefaultValueArgument -> addArgument(argInfo.getArgumentByDefaultValue(element, allUsages, psiFactory))
is ExpressionValueArgument -> {
@@ -413,35 +414,34 @@ class KotlinFunctionCallUsage(
val lastNewArgument = newArgumentList.arguments.lastOrNull()
val oldLastResolvedArgument = getResolvedValueArgument(lastNewParameter?.oldIndex ?: -1) as? ExpressionValueArgument
val lambdaArgumentNotTouched =
lastOldArgument is KtLambdaArgument && oldLastResolvedArgument?.valueArgument == lastOldArgument
lastOldArgument is KtLambdaArgument && oldLastResolvedArgument?.valueArgument == lastOldArgument
val newLambdaArgumentAddedLast = lastNewParameter != null
&& lastNewParameter.isNewParameter
&& lastNewParameter.defaultValueForCall is KtLambdaExpression
&& lastNewArgument != null
&& !lastNewArgument.isNamed()
&& lastNewParameter.isNewParameter
&& lastNewParameter.defaultValueForCall is KtLambdaExpression
&& lastNewArgument != null
&& !lastNewArgument.isNamed()
if (lambdaArgumentNotTouched) {
newArgumentList.removeArgument(newArgumentList.arguments.last())
}
else {
} else {
val lambdaArguments = element.lambdaArguments
if (lambdaArguments.isNotEmpty()) {
element.deleteChildRange(lambdaArguments.first(), lambdaArguments.last())
}
}
var oldArgumentList = element.valueArgumentList.sure { "Argument list is expected: " + element.text }
val oldArgumentList = element.valueArgumentList.sure { "Argument list is expected: " + element.text }
replaceListPsiAndKeepDelimiters(oldArgumentList, newArgumentList) { arguments }
element.accept(
object: KtTreeVisitorVoid() {
override fun visitArgument(argument: KtValueArgument) {
if (argument.generatedArgumentValue) {
argument.generatedArgumentValue = false
argument.addToShorteningWaitSet(SHORTEN_ARGUMENTS_OPTIONS)
}
object : KtTreeVisitorVoid() {
override fun visitArgument(argument: KtValueArgument) {
if (argument.generatedArgumentValue) {
argument.generatedArgumentValue = false
argument.addToShorteningWaitSet(SHORTEN_ARGUMENTS_OPTIONS)
}
}
}
)
var newElement: KtElement = element
@@ -451,12 +451,11 @@ class KotlinFunctionCallUsage(
val extensionReceiverExpression = receiverArgument?.getArgumentExpression()
val defaultValueForCall = newReceiverInfo.defaultValueForCall
val receiver = extensionReceiverExpression?.let { psiFactory.createExpression(it.text) }
?: defaultValueForCall
?: psiFactory.createExpression("_")
?: defaultValueForCall
?: psiFactory.createExpression("_")
psiFactory.createExpressionByPattern("$0.$1", receiver, element)
}
else {
} else {
psiFactory.createExpression(element.text)
}
@@ -489,7 +488,7 @@ class KotlinFunctionCallUsage(
}
companion object {
private val REVERSED_TEXT_OFFSET_COMPARATOR = Comparator<kotlin.Pair<KtElement, KtElement>> { p1, p2 ->
private val REVERSED_TEXT_OFFSET_COMPARATOR = Comparator<Pair<KtElement, KtElement>> { p1, p2 ->
val offset1 = p1.first.startOffset
val offset2 = p2.first.startOffset
when {
@@ -499,7 +498,7 @@ class KotlinFunctionCallUsage(
}
}
private val SHORTEN_ARGUMENTS_OPTIONS = ShortenReferences.Options(true, true)
private val SHORTEN_ARGUMENTS_OPTIONS = ShortenReferences.Options(removeThisLabels = true, removeThis = true)
private fun updateJavaPropertyCall(changeInfo: KotlinChangeInfo, element: KtCallElement): KtElement {
val newReceiverInfo = changeInfo.receiverParameterInfo
@@ -520,8 +519,7 @@ class KotlinFunctionCallUsage(
if (originalReceiverInfo != null) {
firstArgument?.replace(newReceiverArgument)
}
else {
} else {
arguments.addArgumentAfter(newReceiverArgument, null)
}
}
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.idea.refactoring.inline
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.refactoring.JavaRefactoringSettings
import org.jetbrains.kotlin.idea.codeInliner.UsageReplacementStrategy
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
@@ -25,11 +24,11 @@ import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtProperty
class KotlinInlineValDialog(
property: KtProperty,
reference: KtSimpleNameReference?,
private val replacementStrategy: UsageReplacementStrategy,
private val assignmentToDelete: KtBinaryExpression?,
withPreview: Boolean = true
property: KtProperty,
reference: KtSimpleNameReference?,
private val replacementStrategy: UsageReplacementStrategy,
private val assignmentToDelete: KtBinaryExpression?,
withPreview: Boolean = true
) : AbstractKotlinInlineDialog(property, reference) {
private val isLocal = (callable as KtProperty).isLocal
@@ -39,7 +38,7 @@ class KotlinInlineValDialog(
init {
setPreviewResults(withPreview && shouldBeShown())
if (simpleLocal) {
setDoNotAskOption(object : DialogWrapper.DoNotAskOption {
setDoNotAskOption(object : DoNotAskOption {
override fun isToBeShown() = EditorSettingsExternalizable.getInstance().isShowInlineLocalDialog
override fun setToBeShown(value: Boolean, exitCode: Int) {
@@ -62,10 +61,12 @@ class KotlinInlineValDialog(
public override fun doAction() {
invokeRefactoring(
KotlinInlineCallableProcessor(project, replacementStrategy, callable, reference,
inlineThisOnly = isInlineThisOnly,
deleteAfter = !isInlineThisOnly && !isKeepTheDeclaration,
statementToDelete = assignmentToDelete)
KotlinInlineCallableProcessor(
project, replacementStrategy, callable, reference,
inlineThisOnly = isInlineThisOnly,
deleteAfter = !isInlineThisOnly && !isKeepTheDeclaration,
statementToDelete = assignmentToDelete
)
)
val settings = JavaRefactoringSettings.getInstance()
@@ -30,18 +30,20 @@ import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
import org.jetbrains.kotlin.idea.refactoring.introduce.selectElementsWithTargetSibling
import org.jetbrains.kotlin.idea.refactoring.introduce.validateExpressionElements
import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtFile
class ExtractKotlinFunctionHandler(
private val allContainersEnabled: Boolean = false,
private val helper: ExtractionEngineHelper = ExtractKotlinFunctionHandler.InteractiveExtractionHelper) : RefactoringActionHandler {
private val allContainersEnabled: Boolean = false,
private val helper: ExtractionEngineHelper = InteractiveExtractionHelper
) : RefactoringActionHandler {
object InteractiveExtractionHelper : ExtractionEngineHelper(EXTRACT_FUNCTION) {
override fun configureAndRun(
project: Project,
editor: Editor,
descriptorWithConflicts: ExtractableCodeDescriptorWithConflicts,
onFinish: (ExtractionResult) -> Unit
project: Project,
editor: Editor,
descriptorWithConflicts: ExtractableCodeDescriptorWithConflicts,
onFinish: (ExtractionResult) -> Unit
) {
KotlinExtractFunctionDialog(descriptorWithConflicts.descriptor.extractionData.project, descriptorWithConflicts) {
doRefactor(it.currentConfiguration, onFinish)
@@ -50,10 +52,10 @@ class ExtractKotlinFunctionHandler(
}
fun doInvoke(
editor: Editor,
file: KtFile,
elements: List<PsiElement>,
targetSibling: PsiElement
editor: Editor,
file: KtFile,
elements: List<PsiElement>,
targetSibling: PsiElement
) {
val adjustedElements = (elements.singleOrNull() as? KtBlockExpression)?.statements ?: elements
val extractionData = ExtractionData(file, adjustedElements.toRange(false), targetSibling)
@@ -64,14 +66,14 @@ class ExtractKotlinFunctionHandler(
fun selectElements(editor: Editor, file: KtFile, continuation: (elements: List<PsiElement>, targetSibling: PsiElement) -> Unit) {
selectElementsWithTargetSibling(
EXTRACT_FUNCTION,
editor,
file,
"Select target code block",
listOf(CodeInsightUtils.ElementKind.EXPRESSION),
::validateExpressionElements,
{ elements, parent -> parent.getExtractionContainers(elements.size == 1, allContainersEnabled) },
continuation
EXTRACT_FUNCTION,
editor,
file,
"Select target code block",
listOf(CodeInsightUtils.ElementKind.EXPRESSION),
::validateExpressionElements,
{ elements, parent -> parent.getExtractionContainers(elements.size == 1, allContainersEnabled) },
continuation
)
}
@@ -29,12 +29,12 @@ import javax.swing.table.DefaultTableCellRenderer
open class ExtractFunctionParameterTablePanel : AbstractParameterTablePanel<Parameter, ExtractFunctionParameterTablePanel.ParameterInfo>() {
companion object {
val PARAMETER_TYPE_COLUMN = 2
const val PARAMETER_TYPE_COLUMN = 2
}
class ParameterInfo(
originalParameter: Parameter,
val isReceiver: Boolean
originalParameter: Parameter,
val isReceiver: Boolean
) : AbstractParameterTablePanel.AbstractParameterInfo<Parameter>(originalParameter) {
var type = originalParameter.parameterType
@@ -45,7 +45,7 @@ open class ExtractFunctionParameterTablePanel : AbstractParameterTablePanel<Para
override fun toParameter() = originalParameter.copy(name, type)
}
override fun createTableModel(): AbstractParameterTablePanel<Parameter, ParameterInfo>.TableModelBase = MyTableModel()
override fun createTableModel(): TableModelBase = MyTableModel()
override fun createAdditionalColumns() {
with(table.columnModel.getColumn(PARAMETER_TYPE_COLUMN)) {
@@ -54,27 +54,27 @@ open class ExtractFunctionParameterTablePanel : AbstractParameterTablePanel<Para
private val myLabel = JBComboBoxLabel()
override fun getTableCellRendererComponent(
table: JTable, value: Any, isSelected: Boolean, hasFocus: Boolean, row: Int, column: Int
table: JTable, value: Any, isSelected: Boolean, hasFocus: Boolean, row: Int, column: Int
): Component {
myLabel.text = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.renderType(value as KotlinType)
myLabel.background = if (isSelected) table.selectionBackground else table.background
myLabel.foreground = if (isSelected) table.selectionForeground else table.foreground
if (isSelected) {
myLabel.setSelectionIcon()
}
else {
} else {
myLabel.setRegularIcon()
}
return myLabel
}
}
cellEditor = object : AbstractTableCellEditor() {
internal val myEditorComponent = JBComboBoxTableCellEditorComponent()
val myEditorComponent = JBComboBoxTableCellEditorComponent()
override fun getCellEditorValue() = myEditorComponent.editorValue
override fun getTableCellEditorComponent(
table: JTable, value: Any, isSelected: Boolean, row: Int, column: Int): Component {
table: JTable, value: Any, isSelected: Boolean, row: Int, column: Int
): Component {
val info = parameterInfos[row]
myEditorComponent.setCell(table, row, column)
@@ -90,13 +90,13 @@ open class ExtractFunctionParameterTablePanel : AbstractParameterTablePanel<Para
fun init(receiver: Parameter?, parameters: List<Parameter>) {
parameterInfos = parameters.mapTo(
if (receiver != null) arrayListOf(ParameterInfo(receiver, true)) else arrayListOf()
if (receiver != null) arrayListOf(ParameterInfo(receiver, true)) else arrayListOf()
) { ParameterInfo(it, false) }
super.init()
}
private inner class MyTableModel : AbstractParameterTablePanel<Parameter, ParameterInfo>.TableModelBase() {
private inner class MyTableModel : TableModelBase() {
override fun getColumnCount() = 3
override fun getValueAt(rowIndex: Int, columnIndex: Int): Any? {
@@ -117,7 +117,7 @@ open class ExtractFunctionParameterTablePanel : AbstractParameterTablePanel<Para
override fun isCellEditable(rowIndex: Int, columnIndex: Int): Boolean {
val info = parameterInfos[rowIndex]
return when (columnIndex) {
AbstractParameterTablePanel.PARAMETER_NAME_COLUMN -> super.isCellEditable(rowIndex, columnIndex) && !info.isReceiver
PARAMETER_NAME_COLUMN -> super.isCellEditable(rowIndex, columnIndex) && !info.isReceiver
PARAMETER_TYPE_COLUMN -> isEnabled && info.isEnabled && info.originalParameter.getParameterTypeCandidates().size > 1
else -> super.isCellEditable(rowIndex, columnIndex)
}
@@ -67,7 +67,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.DFS.*
import java.util.*
@@ -407,7 +406,7 @@ internal fun ExtractionData.createTemporaryCodeBlock(): KtBlockExpression {
private fun KotlinType.collectReferencedTypes(processTypeArguments: Boolean): List<KotlinType> {
if (!processTypeArguments) return Collections.singletonList(this)
return DFS.dfsFromNode(
return dfsFromNode(
this,
Neighbors<KotlinType> { current -> current.arguments.map { it.type } },
VisitedWithSet(),
@@ -168,7 +168,7 @@ class DuplicateInfo(
)
fun ExtractableCodeDescriptor.findDuplicates(): List<DuplicateInfo> {
fun processWeakMatch(match: UnificationResult.WeaklyMatched, newControlFlow: ControlFlow): Boolean {
fun processWeakMatch(match: WeaklyMatched, newControlFlow: ControlFlow): Boolean {
val valueCount = controlFlow.outputValues.size
val weakMatches = HashMap(match.weakMatches)
@@ -234,7 +234,7 @@ fun ExtractableCodeDescriptor.findDuplicates(): List<DuplicateInfo> {
controlFlow?.let {
DuplicateInfo(range, it, unifierParameters.map { param ->
match.substitution[param]!!.text!!
match.substitution.getValue(param).text!!
})
}
}
@@ -254,14 +254,13 @@ private fun makeCall(
) {
fun insertCall(anchor: PsiElement, wrappedCall: KtExpression): KtExpression? {
val firstExpression = rangeToReplace.elements.firstOrNull { it is KtExpression } as? KtExpression
if (firstExpression?.isLambdaOutsideParentheses() ?: false) {
val functionLiteralArgument = firstExpression?.getStrictParentOfType<KtLambdaArgument>()!!
if (firstExpression?.isLambdaOutsideParentheses() == true) {
val functionLiteralArgument = firstExpression.getStrictParentOfType<KtLambdaArgument>()!!
return functionLiteralArgument.moveInsideParenthesesAndReplaceWith(wrappedCall, extractableDescriptor.originalContext)
}
if (anchor is KtOperationReferenceExpression) {
val operationExpression = anchor.parent as? KtOperationExpression ?: return null
val newNameExpression = when (operationExpression) {
val newNameExpression = when (val operationExpression = anchor.parent as? KtOperationExpression ?: return null) {
is KtUnaryExpression -> OperatorToFunctionIntention.convert(operationExpression).second
is KtBinaryExpression -> {
InfixCallToOrdinaryIntention.convert(operationExpression).getCalleeExpressionIfAny()
@@ -353,7 +352,7 @@ private fun makeCall(
fun wrapCall(outputValue: OutputValue, callText: String): List<PsiElement> {
return when (outputValue) {
is OutputValue.ExpressionValue -> {
is ExpressionValue -> {
val exprText = if (outputValue.callSiteReturn) {
val firstReturn = outputValue.originalExpressions.asSequence().filterIsInstance<KtReturnExpression>().firstOrNull()
val label = firstReturn?.getTargetLabel()?.text ?: ""
@@ -397,7 +396,7 @@ private fun makeCall(
controlFlow.outputValues
.filter { it != defaultValue }
.flatMap { wrapCall(it, unboxingExpressions[it]!!) }
.flatMap { wrapCall(it, unboxingExpressions.getValue(it)) }
.withIndex()
.forEach {
val (i, e) = it
@@ -412,7 +411,7 @@ private fun makeCall(
if (!inlinableCall) {
block.addBefore(newLine, anchorInBlock)
}
insertCall(anchor, wrapCall(it, unboxingExpressions[it]!!).first() as KtExpression)?.removeTemplateEntryBracesIfPossible()
insertCall(anchor, wrapCall(it, unboxingExpressions.getValue(it)).first() as KtExpression)?.removeTemplateEntryBracesIfPossible()
}
if (anchor.isValid) {
@@ -533,7 +532,7 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
}
val originalRef = resolveResult.originalRefExpr
val newRef = descriptor.replacementMap[originalRef]
.fold(currentRef as KtElement) { currentRef, replacement -> replacement(descriptor, currentRef) }
.fold(currentRef as KtElement) { ref, replacement -> replacement(descriptor, ref) }
(newRef as? KtSimpleNameExpression)?.resolveResult = resolveResult
}
@@ -608,7 +607,7 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
}
} else {
(targetContainer.addAfter(declaration, anchor) as KtNamedDeclaration).apply {
if (!(targetContainer is KtClassBody && (targetContainer.parent as? KtClass)?.isEnum() ?: false)) {
if (!(targetContainer is KtClassBody && (targetContainer.parent as? KtClass)?.isEnum() == true)) {
targetContainer.addAfter(emptyLines, anchor)
}
}
@@ -40,28 +40,27 @@ import org.jetbrains.kotlin.psi.KtProperty
import java.util.*
class KotlinIntroducePropertyHandler(
val helper: ExtractionEngineHelper = KotlinIntroducePropertyHandler.InteractiveExtractionHelper
): RefactoringActionHandler {
val helper: ExtractionEngineHelper = InteractiveExtractionHelper
) : RefactoringActionHandler {
object InteractiveExtractionHelper : ExtractionEngineHelper(INTRODUCE_PROPERTY) {
private fun getExtractionTarget(descriptor: ExtractableCodeDescriptor) =
propertyTargets.firstOrNull { it.isAvailable(descriptor) }
propertyTargets.firstOrNull { it.isAvailable(descriptor) }
override fun validate(descriptor: ExtractableCodeDescriptor) =
descriptor.validate(getExtractionTarget(descriptor) ?: ExtractionTarget.FUNCTION)
descriptor.validate(getExtractionTarget(descriptor) ?: ExtractionTarget.FUNCTION)
override fun configureAndRun(
project: Project,
editor: Editor,
descriptorWithConflicts: ExtractableCodeDescriptorWithConflicts,
onFinish: (ExtractionResult) -> Unit
project: Project,
editor: Editor,
descriptorWithConflicts: ExtractableCodeDescriptorWithConflicts,
onFinish: (ExtractionResult) -> Unit
) {
val descriptor = descriptorWithConflicts.descriptor
val target = getExtractionTarget(descriptor)
if (target != null) {
val options = ExtractionGeneratorOptions.DEFAULT.copy(target = target, delayInitialOccurrenceReplacement = true)
doRefactor(ExtractionGeneratorConfiguration(descriptor, options), onFinish)
}
else {
} else {
showErrorHint(project, editor, "Can't introduce property for this expression", INTRODUCE_PROPERTY)
}
}
@@ -69,16 +68,17 @@ class KotlinIntroducePropertyHandler(
fun selectElements(editor: Editor, file: KtFile, continuation: (elements: List<PsiElement>, targetSibling: PsiElement) -> Unit) {
selectElementsWithTargetSibling(
INTRODUCE_PROPERTY,
editor,
file,
"Select target code block",
listOf(CodeInsightUtils.ElementKind.EXPRESSION),
::validateExpressionElements,
{ _, parent ->
parent.getExtractionContainers(strict = true, includeAll = true).filter { it is KtClassBody || (it is KtFile && !it.isScript()) }
},
continuation
INTRODUCE_PROPERTY,
editor,
file,
"Select target code block",
listOf(CodeInsightUtils.ElementKind.EXPRESSION),
::validateExpressionElements,
{ _, parent ->
parent.getExtractionContainers(strict = true, includeAll = true)
.filter { it is KtClassBody || (it is KtFile && !it.isScript()) }
},
continuation
)
}
@@ -100,23 +100,21 @@ class KotlinIntroducePropertyHandler(
}
val introducer = KotlinInplacePropertyIntroducer(
property = property,
editor = editor,
project = project,
title = INTRODUCE_PROPERTY,
doNotChangeVar = false,
exprType = descriptor.returnType,
extractionResult = it,
availableTargets = propertyTargets.filter { it.isAvailable(descriptor) }
property = property,
editor = editor,
project = project,
title = INTRODUCE_PROPERTY,
doNotChangeVar = false,
exprType = descriptor.returnType,
extractionResult = it,
availableTargets = propertyTargets.filter { target -> target.isAvailable(descriptor) }
)
introducer.performInplaceRefactoring(LinkedHashSet(descriptor.suggestedNames))
}
else {
} else {
processDuplicatesSilently(it.duplicateReplacers, project)
}
}
}
else {
} else {
showErrorHintByKey(project, editor, "cannot.refactor.no.expression", INTRODUCE_PROPERTY)
}
}
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.idea.util.psi.patternMatching.UnifierParameter
import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
@@ -63,8 +62,10 @@ fun IntroduceTypeAliasData.analyze(): IntroduceTypeAliasAnalysisResult {
val dummyVar = psiFactory.createProperty("val a: Int").apply {
typeReference!!.replace(
originalTypeElement.parent as? KtTypeReference ?:
if (originalTypeElement is KtTypeElement) psiFactory.createType(originalTypeElement) else psiFactory.createType(originalTypeElement.text))
originalTypeElement.parent as? KtTypeReference ?: if (originalTypeElement is KtTypeElement) psiFactory.createType(
originalTypeElement
) else psiFactory.createType(originalTypeElement.text)
)
}
val newTypeReference = dummyVar.typeReference!!
val newReferences = newTypeReference.collectDescendantsOfType<KtTypeReference> { it.resolveInfo != null }
@@ -86,12 +87,11 @@ fun IntroduceTypeAliasData.analyze(): IntroduceTypeAliasAnalysisResult {
}
val equivalenceRepresentative = groupedReferencesToExtract
.keySet()
.firstOrNull { unifier.unify(it.reference, resolveInfo.reference).matched }
.keySet()
.firstOrNull { unifier.unify(it.reference, resolveInfo.reference).matched }
if (equivalenceRepresentative != null) {
groupedReferencesToExtract.putValue(equivalenceRepresentative, resolveInfo)
}
else {
} else {
groupedReferencesToExtract.putValue(resolveInfo, resolveInfo)
}
@@ -109,7 +109,7 @@ fun IntroduceTypeAliasData.analyze(): IntroduceTypeAliasAnalysisResult {
val typeParameterNames = KotlinNameSuggester.suggestNamesForTypeParameters(brokenReferences.size, typeParameterNameValidator)
val typeParameters = (typeParameterNames zip brokenReferences).map { TypeParameter(it.first, groupedReferencesToExtract[it.second]) }
if (typeParameters.any { it.typeReferenceInfos.any { it.reference.typeElement == originalTypeElement } }) {
if (typeParameters.any { it.typeReferenceInfos.any { info -> info.reference.typeElement == originalTypeElement } }) {
return IntroduceTypeAliasAnalysisResult.Error("Type alias cannot refer to types which aren't accessible in the scope where it's defined")
}
@@ -122,13 +122,10 @@ fun IntroduceTypeAliasData.analyze(): IntroduceTypeAliasAnalysisResult {
return IntroduceTypeAliasAnalysisResult.Success(descriptor.copy(name = initialName))
}
fun IntroduceTypeAliasData.getApplicableVisibilities(): List<KtModifierKeywordToken>{
val parent = targetSibling.parent
return when (parent) {
is KtClassBody -> listOf(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD)
is KtFile -> listOf(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD)
else -> emptyList()
}
fun IntroduceTypeAliasData.getApplicableVisibilities(): List<KtModifierKeywordToken> = when (targetSibling.parent) {
is KtClassBody -> listOf(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD)
is KtFile -> listOf(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD)
else -> emptyList()
}
fun IntroduceTypeAliasDescriptor.validate(): IntroduceTypeAliasDescriptorWithConflicts {
@@ -188,9 +185,11 @@ fun findDuplicates(typeAlias: KtTypeAlias): Map<KotlinPsiRange, () -> Unit> {
val typeArgumentList = callExpression.typeArgumentList
if (arguments.isNotEmpty()) {
val newTypeArgumentList = psiFactory.createTypeArguments(typeArgumentsText)
typeArgumentList?.replace(newTypeArgumentList) ?: callExpression.addAfter(newTypeArgumentList, callExpression.calleeExpression)
}
else {
typeArgumentList?.replace(newTypeArgumentList) ?: callExpression.addAfter(
newTypeArgumentList,
callExpression.calleeExpression
)
} else {
typeArgumentList?.delete()
}
callExpression.calleeExpression?.replace(psiFactory.createExpression(aliasName))
@@ -217,39 +216,38 @@ fun findDuplicates(typeAlias: KtTypeAlias): Map<KotlinPsiRange, () -> Unit> {
if (callElement != null) {
occurrence = callElement
arguments = callElement.typeArguments.mapNotNull { it.typeReference?.typeElement }
}
else {
} else {
val userType = element.getParentOfTypeAndBranch<KtUserType> { referenceExpression }
if (userType != null) {
occurrence = userType
arguments = userType.typeArgumentsAsTypes.mapNotNull { it.typeElement }
}
else continue
} else continue
}
if (arguments.size != typeAliasDescriptor.declaredTypeParameters.size) continue
if (TypeUtils.isNullableType(typeAliasDescriptor.underlyingType)
&& occurrence is KtUserType
&& occurrence.parent !is KtNullableType) continue
&& occurrence.parent !is KtNullableType
) continue
rangesWithReplacers += occurrence.toRange() to { replaceOccurrence(occurrence, arguments) }
}
}
typeAlias
.getTypeReference()
?.typeElement
.toRange()
.match(typeAlias.parent, unifier)
.asSequence()
.filter { !(it.range.getTextRange().intersects(aliasRange)) }
.mapNotNullTo(rangesWithReplacers) { match ->
val occurrence = match.range.elements.singleOrNull() as? KtTypeElement ?: return@mapNotNullTo null
val arguments = unifierParameters.mapNotNull { (match.substitution[it] as? KtTypeReference)?.typeElement }
if (arguments.size != unifierParameters.size) return@mapNotNullTo null
match.range to { replaceOccurrence(occurrence, arguments) }
}
.getTypeReference()
?.typeElement
.toRange()
.match(typeAlias.parent, unifier)
.asSequence()
.filter { !(it.range.getTextRange().intersects(aliasRange)) }
.mapNotNullTo(rangesWithReplacers) { match ->
val occurrence = match.range.elements.singleOrNull() as? KtTypeElement ?: return@mapNotNullTo null
val arguments = unifierParameters.mapNotNull { (match.substitution[it] as? KtTypeReference)?.typeElement }
if (arguments.size != unifierParameters.size) return@mapNotNullTo null
match.range to { replaceOccurrence(occurrence, arguments) }
}
return rangesWithReplacers.toMap()
}
private var KtTypeReference.typeParameterInfo : TypeParameter? by CopyablePsiUserDataProperty(Key.create("TYPE_PARAMETER_INFO"))
private var KtTypeReference.typeParameterInfo: TypeParameter? by CopyablePsiUserDataProperty(Key.create("TYPE_PARAMETER_INFO"))
fun IntroduceTypeAliasDescriptor.generateTypeAlias(previewOnly: Boolean = false): KtTypeAlias {
val originalElement = originalData.originalTypeElement
@@ -263,11 +261,10 @@ fun IntroduceTypeAliasDescriptor.generateTypeAlias(previewOnly: Boolean = false)
val typeParameterNames = typeParameters.map { it.name }
val typeAlias = if (originalElement is KtTypeElement) {
psiFactory.createTypeAlias(name, typeParameterNames, originalElement)
}
else {
} else {
psiFactory.createTypeAlias(name, typeParameterNames, originalElement.text)
}
if (visibility != null && visibility != KtTokens.DEFAULT_VISIBILITY_KEYWORD) {
if (visibility != null && visibility != DEFAULT_VISIBILITY_KEYWORD) {
typeAlias.addModifier(visibility)
}
@@ -279,8 +276,7 @@ fun IntroduceTypeAliasDescriptor.generateTypeAlias(previewOnly: Boolean = false)
fun replaceUsage() {
val aliasInstanceText = if (typeParameters.isNotEmpty()) {
"$name<${typeParameters.joinToString { it.typeReferenceInfos.first().reference.text }}>"
}
else {
} else {
name
}
when (originalElement) {
@@ -300,8 +296,7 @@ fun IntroduceTypeAliasDescriptor.generateTypeAlias(previewOnly: Boolean = false)
return if (previewOnly) {
introduceTypeParameters()
typeAlias
}
else {
} else {
replaceUsage()
introduceTypeParameters()
insertDeclaration(typeAlias, originalData.targetSibling)
@@ -29,9 +29,9 @@ import org.jetbrains.kotlin.psi.KtProperty
import javax.swing.Icon
class KotlinMemberSelectionTable(
memberInfos: List<KotlinMemberInfo>,
memberInfoModel: MemberInfoModel<KtNamedDeclaration, KotlinMemberInfo>?,
abstractColumnHeader: String?
memberInfos: List<KotlinMemberInfo>,
memberInfoModel: MemberInfoModel<KtNamedDeclaration, KotlinMemberInfo>?,
abstractColumnHeader: String?
) : AbstractMemberSelectionTable<KtNamedDeclaration, KotlinMemberInfo>(memberInfos, memberInfoModel, abstractColumnHeader) {
override fun getAbstractColumnValue(memberInfo: KotlinMemberInfo): Any? {
if (memberInfo.isStatic || memberInfo.isCompanionMember) return null
@@ -66,7 +66,7 @@ class KotlinMemberSelectionTable(
}
override fun getOverrideIcon(memberInfo: KotlinMemberInfo): Icon? {
val defaultIcon = AbstractMemberSelectionTable.EMPTY_OVERRIDE_ICON
val defaultIcon = EMPTY_OVERRIDE_ICON
val member = memberInfo.member
if (member !is KtNamedFunction && member !is KtProperty && member !is KtParameter) return defaultIcon
@@ -30,7 +30,6 @@ import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot
import org.jetbrains.jps.model.serialization.facet.JpsFacetSerializer
import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer
import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer.*
import org.jetbrains.kotlin.analyzer.common.CommonPlatform
import org.jetbrains.kotlin.config.getFacetPlatformByConfigurationElement
@@ -74,7 +73,7 @@ class KotlinNonJvmSourceRootConverterProvider : ConverterProvider("kotlin-non-jv
val moduleSettingsImpl = moduleSettings as? ModuleSettingsImpl ?: return VirtualFile.EMPTY_ARRAY
return contextImpl
.getClassRoots(element, moduleSettingsImpl)
.mapNotNull { it.toVirtualFile()?.let { JarFileSystem.getInstance().getJarRootForLocalFile(it) } }
.mapNotNull { it.toVirtualFile()?.let { file -> JarFileSystem.getInstance().getJarRootForLocalFile(file) } }
.toTypedArray()
}
}
@@ -83,7 +82,7 @@ class KotlinNonJvmSourceRootConverterProvider : ConverterProvider("kotlin-non-jv
override val explicitKind: PersistentLibraryKind<*>?
get() = (library as? LibraryEx)?.kind
override fun getRoots() = library.getFiles(OrderRootType.CLASSES)
override fun getRoots(): Array<VirtualFile> = library.getFiles(OrderRootType.CLASSES)
}
abstract val explicitKind: PersistentLibraryKind<*>?
@@ -109,16 +108,14 @@ class KotlinNonJvmSourceRootConverterProvider : ConverterProvider("kotlin-non-jv
private fun findProjectLibrary(name: String) = projectLibrariesByName[name]?.firstOrNull()
private fun createLibInfo(orderEntryElement: Element, moduleSettings: ModuleSettings): LibInfo? {
val entryType = orderEntryElement.getAttributeValue(ORDER_ENTRY_TYPE_ATTR)
return when (entryType) {
JpsModuleRootModelSerializer.MODULE_LIBRARY_TYPE -> {
return when (orderEntryElement.getAttributeValue(ORDER_ENTRY_TYPE_ATTR)) {
MODULE_LIBRARY_TYPE -> {
orderEntryElement.getChild(LIBRARY_TAG)?.let { LibInfo.ByXml(it, context, moduleSettings) }
}
JpsModuleRootModelSerializer.LIBRARY_TYPE -> {
LIBRARY_TYPE -> {
val libraryName = orderEntryElement.getAttributeValue(NAME_ATTRIBUTE) ?: return null
val level = orderEntryElement.getAttributeValue(LEVEL_ATTRIBUTE)
when (level) {
when (orderEntryElement.getAttributeValue(LEVEL_ATTRIBUTE)) {
LibraryTablesRegistrar.PROJECT_LEVEL ->
findProjectLibrary(libraryName)?.let { LibInfo.ByXml(it, context, moduleSettings) }
LibraryTablesRegistrar.APPLICATION_LEVEL ->
@@ -147,8 +144,7 @@ class KotlinNonJvmSourceRootConverterProvider : ConverterProvider("kotlin-non-jv
.asSequence()
.mapNotNull { createLibInfo(it, this) }
.forEach {
val platform = it.platform
when (platform) {
when (val platform = it.platform) {
is CommonPlatform -> {
if (!hasCommonStdlib && it.isStdlib) {
hasCommonStdlib = true
@@ -189,7 +185,7 @@ class KotlinNonJvmSourceRootConverterProvider : ConverterProvider("kotlin-non-jv
if (settings.isExternalModule()) return false
val hasMigrationRoots = settings.getSourceFolderElements().any {
JpsModuleRootModelSerializer.loadSourceRoot(it).rootType in rootTypesToMigrate
loadSourceRoot(it).rootType in rootTypesToMigrate
}
if (!hasMigrationRoots) {
return false
@@ -202,8 +198,8 @@ class KotlinNonJvmSourceRootConverterProvider : ConverterProvider("kotlin-non-jv
override fun process(settings: ModuleSettings) {
for (sourceFolder in settings.getSourceFolderElements()) {
val contentRoot = sourceFolder.parent as? Element ?: continue
val oldSourceRoot = JpsModuleRootModelSerializer.loadSourceRoot(sourceFolder)
val url = sourceFolder.getAttributeValue(JpsModuleRootModelSerializer.URL_ATTRIBUTE)
val oldSourceRoot = loadSourceRoot(sourceFolder)
val url = sourceFolder.getAttributeValue(URL_ATTRIBUTE)
val (newRootType, data) = oldSourceRoot.getMigratedSourceRootTypeWithProperties() ?: continue
@Suppress("UNCHECKED_CAST")
@@ -211,7 +207,7 @@ class KotlinNonJvmSourceRootConverterProvider : ConverterProvider("kotlin-non-jv
as? JpsTypedModuleSourceRoot<JpsElement> ?: continue
contentRoot.removeContent(sourceFolder)
JpsModuleRootModelSerializer.saveSourceRoot(contentRoot, url, newSourceRoot)
saveSourceRoot(contentRoot, url, newSourceRoot)
}
}
}
@@ -41,7 +41,9 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.ReturnValueInstruction
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.traverse
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.*
import org.jetbrains.kotlin.idea.core.isOverridable
@@ -85,19 +87,19 @@ private fun KtDeclaration.processHierarchyUpward(scope: AnalysisScope, processor
.mapNotNull { it.source.getPsi() }
.filter { scope.contains(it) }
.toList()
.forEach(processor)
.forEach(processor)
}
private fun KtFunction.processCalls(scope: SearchScope, processor: (UsageInfo) -> Unit) {
processAllExactUsages(
{
KotlinFunctionFindUsagesOptions(project).apply {
isSearchForTextOccurrences = false
isSkipImportStatements = true
searchScope = scope.intersectWith(useScope)
}
},
processor
{
KotlinFunctionFindUsagesOptions(project).apply {
isSearchForTextOccurrences = false
isSkipImportStatements = true
searchScope = scope.intersectWith(useScope)
}
},
processor
)
}
@@ -106,31 +108,32 @@ private enum class AccessKind {
}
private fun KtDeclaration.processVariableAccesses(
scope: SearchScope,
kind: AccessKind,
processor: (UsageInfo) -> Unit
scope: SearchScope,
kind: AccessKind,
processor: (UsageInfo) -> Unit
) {
processAllExactUsages(
{
KotlinPropertyFindUsagesOptions(project).apply {
isReadAccess = kind == AccessKind.READ_ONLY || kind == AccessKind.READ_OR_WRITE
isWriteAccess = kind == AccessKind.WRITE_ONLY || kind == AccessKind.WRITE_WITH_OPTIONAL_READ || kind == AccessKind.READ_OR_WRITE
isReadWriteAccess = kind == AccessKind.WRITE_WITH_OPTIONAL_READ || kind == AccessKind.READ_OR_WRITE
isSearchForTextOccurrences = false
isSkipImportStatements = true
searchScope = scope.intersectWith(useScope)
}
},
processor
{
KotlinPropertyFindUsagesOptions(project).apply {
isReadAccess = kind == AccessKind.READ_ONLY || kind == AccessKind.READ_OR_WRITE
isWriteAccess =
kind == AccessKind.WRITE_ONLY || kind == AccessKind.WRITE_WITH_OPTIONAL_READ || kind == AccessKind.READ_OR_WRITE
isReadWriteAccess = kind == AccessKind.WRITE_WITH_OPTIONAL_READ || kind == AccessKind.READ_OR_WRITE
isSearchForTextOccurrences = false
isSkipImportStatements = true
searchScope = scope.intersectWith(useScope)
}
},
processor
)
}
private fun KtParameter.canProcess() = !isVarArg
abstract class Slicer(
protected val element: KtExpression,
protected val processor: Processor<SliceUsage>,
protected val parentUsage: KotlinSliceUsage
protected val element: KtExpression,
protected val processor: Processor<SliceUsage>,
protected val parentUsage: KotlinSliceUsage
) {
protected class PseudocodeCache {
private val computedPseudocodes = HashMap<KtElement, Pseudocode>()
@@ -138,7 +141,8 @@ abstract class Slicer(
operator fun get(element: KtElement): Pseudocode? {
val container = element.containingDeclarationForPseudocode ?: return null
return computedPseudocodes.getOrPut(container) {
container.getContainingPseudocode(container.analyzeWithContent())?.apply { computedPseudocodes[container] = this } ?: return null
container.getContainingPseudocode(container.analyzeWithContent())?.apply { computedPseudocodes[container] = this }
?: return null
}
}
}
@@ -146,8 +150,8 @@ abstract class Slicer(
protected val pseudocodeCache = PseudocodeCache()
protected fun PsiElement.passToProcessor(
lambdaLevel: Int = parentUsage.lambdaLevel,
forcedExpressionMode: Boolean = false
lambdaLevel: Int = parentUsage.lambdaLevel,
forcedExpressionMode: Boolean = false
) {
processor.process(KotlinSliceUsage(this, parentUsage, lambdaLevel, forcedExpressionMode))
}
@@ -156,9 +160,9 @@ abstract class Slicer(
}
class InflowSlicer(
element: KtExpression,
processor: Processor<SliceUsage>,
parentUsage: KotlinSliceUsage
element: KtExpression,
processor: Processor<SliceUsage>,
parentUsage: KotlinSliceUsage
) : Slicer(element, processor, parentUsage) {
private fun PsiElement.processHierarchyDownwardAndPass() {
processHierarchyDownward(parentUsage.scope.toSearchScope()) { passToProcessor() }
@@ -167,7 +171,7 @@ class InflowSlicer(
private fun PsiElement.passToProcessorAsValue(lambdaLevel: Int = parentUsage.lambdaLevel) = passToProcessor(lambdaLevel, true)
private fun KtDeclaration.processAssignments(accessSearchScope: SearchScope) {
processVariableAccesses(accessSearchScope, AccessKind.WRITE_WITH_OPTIONAL_READ) body@ {
processVariableAccesses(accessSearchScope, AccessKind.WRITE_WITH_OPTIONAL_READ) body@{
val refElement = it.element ?: return@body
val refParent = refElement.parent
@@ -176,8 +180,7 @@ class InflowSlicer(
val (accessKind, accessExpression) = refElement.readWriteAccessWithFullExpression(true)
if (accessKind == ReferenceAccess.WRITE && accessExpression is KtBinaryExpression && accessExpression.operationToken == KtTokens.EQ) {
accessExpression.right
}
else {
} else {
accessExpression
}
}
@@ -191,9 +194,9 @@ class InflowSlicer(
}
private fun KtPropertyAccessor.processBackingFieldAssignments() {
forEachDescendantOfType<KtBinaryExpression> body@ {
forEachDescendantOfType<KtBinaryExpression> body@{
if (it.operationToken != KtTokens.EQ) return@body
val lhs = it.left?.let { KtPsiUtil.safeDeparenthesize(it) } ?: return@body
val lhs = it.left?.let { expression -> KtPsiUtil.safeDeparenthesize(expression) } ?: return@body
val rhs = it.right ?: return@body
if (!lhs.isBackingFieldReference()) return@body
rhs.passToProcessor()
@@ -229,8 +232,7 @@ class InflowSlicer(
if (isDefaultGetter) {
if (isDefaultSetter) {
processPropertyAssignments()
}
else {
} else {
setter!!.processBackingFieldAssignments()
}
}
@@ -249,17 +251,18 @@ class InflowSlicer(
if (function is KtNamedFunction
&& function.name == OperatorNameConventions.SET_VALUE.asString()
&& function.hasModifier(KtTokens.OPERATOR_KEYWORD)) {
&& function.hasModifier(KtTokens.OPERATOR_KEYWORD)
) {
ReferencesSearch
.search(function, parentUsage.scope.toSearchScope())
.filterIsInstance<KtPropertyDelegationMethodsReference>()
.forEach { (it.element?.parent as? KtProperty)?.processPropertyAssignments() }
.search(function, parentUsage.scope.toSearchScope())
.filterIsInstance<KtPropertyDelegationMethodsReference>()
.forEach { (it.element.parent as? KtProperty)?.processPropertyAssignments() }
}
val parameterDescriptor = resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return
(function as? KtFunction)?.processCalls(parentUsage.scope.toSearchScope()) body@ {
(function as? KtFunction)?.processCalls(parentUsage.scope.toSearchScope()) body@{
val refElement = it.element ?: return@body
val refParent = refElement.parent
@@ -267,8 +270,7 @@ class InflowSlicer(
refElement is KtExpression -> {
val callElement = refElement.getParentOfTypeAndBranch<KtCallElement> { calleeExpression } ?: return@body
val resolvedCall = callElement.resolveToCall() ?: return@body
val resolvedArgument = resolvedCall.valueArguments[parameterDescriptor] ?: return@body
when (resolvedArgument) {
when (val resolvedArgument = resolvedCall.valueArguments[parameterDescriptor] ?: return@body) {
is DefaultValueArgument -> defaultValue
is ExpressionValueArgument -> resolvedArgument.valueArgument?.getArgumentExpression()
else -> null
@@ -307,8 +309,8 @@ class InflowSlicer(
private fun KtExpression.isBackingFieldReference(): Boolean {
return this is KtSimpleNameExpression &&
getReferencedName() == SyntheticFieldDescriptor.NAME.asString() &&
resolveToCall()?.resultingDescriptor is SyntheticFieldDescriptor
getReferencedName() == SyntheticFieldDescriptor.NAME.asString() &&
resolveToCall()?.resultingDescriptor is SyntheticFieldDescriptor
}
private fun KtExpression.processExpression() {
@@ -326,8 +328,7 @@ class InflowSlicer(
val pseudocode = pseudocodeCache[this] ?: return
val expressionValue = pseudocode.getElementValue(this) ?: return
val createdAt = expressionValue.createdAt
when (createdAt) {
when (val createdAt = expressionValue.createdAt) {
is ReadValueInstruction -> {
if (createdAt.target == AccessTarget.BlackBox) {
val originalElement = expressionValue.element as? KtExpression ?: return
@@ -340,10 +341,9 @@ class InflowSlicer(
val accessedDeclaration = accessedDescriptor.source.getPsi() ?: return
if (accessedDescriptor is SyntheticFieldDescriptor) {
val property = accessedDeclaration as? KtProperty ?: return
if (accessedDescriptor.propertyDescriptor.setter?.isDefault ?: true) {
if (accessedDescriptor.propertyDescriptor.setter?.isDefault != false) {
property.processPropertyAssignments()
}
else {
} else {
property.setter?.processBackingFieldAssignments()
}
return
@@ -369,8 +369,7 @@ class InflowSlicer(
val resultingDescriptor = resolvedCall.resultingDescriptor
if (resultingDescriptor is FunctionInvokeDescriptor) {
(resolvedCall.dispatchReceiver as? ExpressionReceiver)?.expression?.passToProcessorAsValue(parentUsage.lambdaLevel + 1)
}
else {
} else {
resultingDescriptor.source.getPsi()?.processHierarchyDownwardAndPass()
}
}
@@ -390,9 +389,9 @@ class InflowSlicer(
}
class OutflowSlicer(
element: KtExpression,
processor: Processor<SliceUsage>,
parentUsage: KotlinSliceUsage
element: KtExpression,
processor: Processor<SliceUsage>,
parentUsage: KotlinSliceUsage
) : Slicer(element, processor, parentUsage) {
private fun KtDeclaration.processVariable() {
processHierarchyUpward(parentUsage.scope) {
@@ -400,7 +399,7 @@ class OutflowSlicer(
val withDereferences = parentUsage.params.showInstanceDereferences
val accessKind = if (withDereferences) AccessKind.READ_OR_WRITE else AccessKind.READ_ONLY
(this as? KtDeclaration)?.processVariableAccesses(parentUsage.scope.toSearchScope(), accessKind) body@ {
(this as? KtDeclaration)?.processVariableAccesses(parentUsage.scope.toSearchScope(), accessKind) body@{
val refElement = it.element
if (refElement !is KtExpression) {
refElement?.passToProcessor()
@@ -442,22 +441,19 @@ class OutflowSlicer(
processHierarchyUpward(parentUsage.scope) {
if (this is KtFunction) {
processCalls(parentUsage.scope.toSearchScope()) {
val refElement = it.element
when {
refElement == null -> (it.reference as? LightMemberReference)?.element?.passToProcessor()
refElement is KtExpression -> {
when (val refElement = it.element) {
null -> (it.reference as? LightMemberReference)?.element?.passToProcessor()
is KtExpression -> {
refElement.getCallElementForExactCallee()?.passToProcessor()
refElement.getCallableReferenceForExactCallee()?.passToProcessor(parentUsage.lambdaLevel + 1)
}
else -> refElement.passToProcessor()
}
}
}
else if (this is PsiMethod && language == JavaLanguage.INSTANCE) {
} else if (this is PsiMethod && language == JavaLanguage.INSTANCE) {
// todo: work around the bug in JavaSliceProvider.transform()
processor.process(JavaSliceUsage.createRootUsage(this, parentUsage.params))
}
else {
} else {
passToProcessor()
}
}
@@ -465,26 +461,26 @@ class OutflowSlicer(
}
val funExpression = when (this) {
is KtFunctionLiteral -> parent as? KtLambdaExpression
is KtNamedFunction -> this
else -> null
} ?: return
is KtFunctionLiteral -> parent as? KtLambdaExpression
is KtNamedFunction -> this
else -> null
} ?: return
(funExpression as PsiElement).passToProcessor(parentUsage.lambdaLevel + 1, true)
}
private fun processDereferenceIsNeeded(
expression: KtExpression,
pseudoValue: PseudoValue,
instr: InstructionWithReceivers
expression: KtExpression,
pseudoValue: PseudoValue,
instr: InstructionWithReceivers
) {
if (!parentUsage.params.showInstanceDereferences) return
val receiver = instr.receiverValues[pseudoValue]
val resolvedCall = when (instr) {
is CallInstruction -> instr.resolvedCall
is ReadValueInstruction -> (instr.target as? AccessTarget.Call)?.resolvedCall
else -> null
} ?: return
is CallInstruction -> instr.resolvedCall
is ReadValueInstruction -> (instr.target as? AccessTarget.Call)?.resolvedCall
else -> null
} ?: return
if (receiver != null && resolvedCall.dispatchReceiver == receiver) {
processor.process(KotlinSliceDereferenceUsage(expression, parentUsage, parentUsage.lambdaLevel))
@@ -513,15 +509,15 @@ class OutflowSlicer(
is CallInstruction -> {
if (parentUsage.lambdaLevel > 0 && instr.receiverValues[pseudoValue] != null) {
instr.element.passToProcessor(parentUsage.lambdaLevel - 1)
}
else {
} else {
instr.arguments[pseudoValue]?.source?.getPsi()?.passToProcessor()
}
}
is ReturnValueInstruction -> instr.subroutine.passToProcessor()
is MagicInstruction -> when (instr.kind) {
MagicKind.NOT_NULL_ASSERTION, MagicKind.CAST -> instr.outputValue.element?.passToProcessor()
else -> { }
else -> {
}
}
}
}
@@ -63,8 +63,8 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention<KtNamedDeclaration
if (element.resolveToDescriptorIfAny() == null) return null
return TextRange(
element.startOffset,
element.getSuperTypeList()?.startOffset ?: element.getBody()?.startOffset ?: element.endOffset
element.startOffset,
element.getSuperTypeList()?.startOffset ?: element.body?.startOffset ?: element.endOffset
)
}
@@ -105,8 +105,8 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention<KtNamedDeclaration
val baseName = kotlinFile.nameWithoutExtension
val psiDir = kotlinFile.parent!!.toPsiDirectory(project)!!
return generateSequence(0) { it + 1 }
.map { "$baseName$it" }
.first { psiDir.findFile("$it.java") == null && findTestClass(psiDir, it) == null }
.map { "$baseName$it" }
.first { psiDir.findFile("$it.java") == null && findTestClass(psiDir, it) == null }
}
// Based on the com.intellij.testIntegration.createTest.CreateTestAction.CreateTestAction.invoke()
@@ -114,18 +114,20 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention<KtNamedDeclaration
val srcModule = ModuleUtilCore.findModuleForPsiElement(element) ?: return
val propertiesComponent = PropertiesComponent.getInstance()
val testFolders = HashSet<VirtualFile>()
CreateTestAction.checkForTestRoots(srcModule, testFolders)
checkForTestRoots(srcModule, testFolders)
if (testFolders.isEmpty() && !propertiesComponent.getBoolean("create.test.in.the.same.root")) {
if (Messages.showOkCancelDialog(
project,
"Create test in the same source root?",
"No Test Roots Found",
Messages.getQuestionIcon()) != Messages.OK) return
Messages.getQuestionIcon()
) != Messages.OK
) return
propertiesComponent.setValue("create.test.in.the.same.root", true)
}
val srcClass = CreateTestAction.getContainingClass(element) ?: return
val srcClass = getContainingClass(element) ?: return
val srcDir = element.containingFile.containingDirectory
val srcPackage = JavaDirectoryService.getInstance().getPackage(srcDir)
@@ -137,12 +139,12 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention<KtNamedDeclaration
if (existingClass != null) {
// TODO: Override dialog method when it becomes protected
val answer = Messages.showYesNoDialog(
project,
"Kotlin class '${existingClass.name}' already exists. Do you want to update it?",
CommonBundle.getErrorTitle(),
"Rewrite",
"Cancel",
Messages.getErrorIcon()
project,
"Kotlin class '${existingClass.name}' already exists. Do you want to update it?",
CommonBundle.getErrorTitle(),
"Rewrite",
"Cancel",
Messages.getErrorIcon()
)
if (answer == Messages.NO) return
}
@@ -163,7 +165,7 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention<KtNamedDeclaration
if (generatedClass.language == JavaLanguage.INSTANCE) {
project.executeCommand("Convert class '${generatedClass.name}' to Kotlin", this) {
runWriteAction {
generatedClass.methods.forEach { it.throwsList.referenceElements.forEach { it.delete() } }
generatedClass.methods.forEach { it.throwsList.referenceElements.forEach { referenceElement -> referenceElement.delete() } }
}
if (existingClass != null) {
@@ -172,16 +174,15 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention<KtNamedDeclaration
.declarations
.asSequence()
.filterIsInstance<KtNamedFunction>()
.mapTo(HashSet()) { it.name }
.mapTo(HashSet()) { it.name }
generatedClass
.methods
.filter { it.name !in existingMethodNames }
.forEach { it.j2k()?.let { existingClass.addDeclaration(it) } }
.methods
.filter { it.name !in existingMethodNames }
.forEach { it.j2k()?.let { declaration -> existingClass.addDeclaration(declaration) } }
generatedClass.delete()
}
NavigationUtil.activateFileWithPsiElement(existingClass)
}
else {
} else {
with(PsiDocumentManager.getInstance(project)) {
getDocument(generatedFile)?.let { doPostponedOperationsAndUnblockDocument(it) }
}
@@ -20,7 +20,6 @@ import com.intellij.openapi.fileTypes.StdFileTypes
import com.intellij.util.indexing.DataIndexer
import com.intellij.util.indexing.FileBasedIndex
import com.intellij.util.indexing.FileContent
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.*
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
@@ -76,7 +75,7 @@ object KotlinJvmMetadataVersionIndex : KotlinMetadataVersionIndexBase<KotlinJvmM
kind = KotlinClassHeader.Kind.getById(value)
}
METADATA_EXTRA_INT_FIELD_NAME -> if (value is Int) {
isStrictSemantics = (value and JvmAnnotationNames.METADATA_STRICT_VERSION_SEMANTICS_FLAG) != 0
isStrictSemantics = (value and METADATA_STRICT_VERSION_SEMANTICS_FLAG) != 0
}
}
}