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