Fix 'Redundant qualifier name' warnings & refactoring in idea

This commit is contained in:
Dmitry Gridin
2019-04-09 21:07:31 +07:00
parent 646f325f57
commit f3faae7bb4
50 changed files with 779 additions and 763 deletions
@@ -41,7 +41,7 @@ class KotlinGenerateEqualsWizard(
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>()
@@ -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
@@ -56,7 +56,7 @@ 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(
@@ -64,7 +64,7 @@ class KotlinReferenceData(
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(
DataFlavor.javaJVMLocalObjectMimeType + ";class=" + dataClass.name,
"KotlinReferenceData", "KotlinReferenceData",
dataClass.classLoader) dataClass.classLoader
} )
catch (e: NoClassDefFoundError) { } catch (e: NoClassDefFoundError) {
null null
} } catch (e: IllegalArgumentException) {
catch (e: IllegalArgumentException) {
null null
} }
} }
@@ -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) =
@@ -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
} }
@@ -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)
} }
} }
@@ -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) {
@@ -49,11 +49,11 @@ 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")
@@ -65,9 +65,9 @@ class KotlinOverrideHierarchyBrowser(
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
@@ -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
@@ -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
} }
@@ -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
@@ -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())
} }
} }
@@ -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(
expression,
"Recursive property accessor", "Recursive property accessor",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
ReplaceWithFieldFix()) ReplaceWithFieldFix()
} )
else if (isRecursiveSyntheticPropertyAccess(expression)) { } else if (isRecursiveSyntheticPropertyAccess(expression)) {
holder.registerProblem(expression, holder.registerProblem(
expression,
"Recursive synthetic property accessor", "Recursive synthetic property accessor",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING) ProblemHighlightType.GENERIC_ERROR_OR_WARNING
)
} }
} }
} }
@@ -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,7 +106,8 @@ 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)
} }
@@ -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
@@ -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)
} }
@@ -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
@@ -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 {
@@ -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)
} }
} }
} }
@@ -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
} }
} }
@@ -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
} }
} }
@@ -169,7 +166,7 @@ abstract class ChangeCallableReturnTypeFix(
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)
} }
} }
@@ -181,17 +178,18 @@ abstract class ChangeCallableReturnTypeFix(
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
@@ -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(
userDeclaration, userDescriptor,
targetUserVisibility, PRIVATE, targetUserVisibility, PRIVATE,
protectedAllowed, result) protectedAllowed, result
)
} }
} }
addFixToTargetVisibility(exposedDeclaration, exposedDescriptor, addFixToTargetVisibility(
exposedDeclaration, exposedDescriptor,
targetExposedVisibility, PUBLIC, targetExposedVisibility, PUBLIC,
protectedAllowed, result) protectedAllowed, result
)
return result return result
} }
} }
@@ -96,13 +96,12 @@ sealed class CreateLabelFix(
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 '?'"),
@@ -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,
@@ -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
@@ -50,13 +53,14 @@ 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(
superCallables: Collection<CallableDescriptor>,
callableFromEditor: CallableDescriptor, callableFromEditor: CallableDescriptor,
options: List<String>): Int { 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(
"x.overrides.y.in.class.list",
DescriptorRenderer.COMPACT.render(callableFromEditor), DescriptorRenderer.COMPACT.render(callableFromEditor),
superString, superString,
"refactor") "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)
@@ -101,8 +109,7 @@ abstract class CallableRefactoring<out T: CallableDescriptor>(
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
} }
@@ -183,8 +189,7 @@ 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
@@ -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
@@ -72,7 +71,11 @@ open class KotlinChangeInfo(
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)
)
} }
} }
@@ -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)
} }
} }
@@ -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('.')
@@ -332,8 +333,8 @@ open class KotlinChangeInfo(
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)!!)
} }
@@ -358,7 +359,8 @@ 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,7 +386,8 @@ 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(
originalPsiMethod: PsiMethod,
currentPsiMethod: PsiMethod, currentPsiMethod: PsiMethod,
newName: String, newName: String,
newReturnType: PsiType?, newReturnType: PsiType?,
@@ -427,7 +430,8 @@ 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
@@ -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))
} }
@@ -548,7 +551,7 @@ fun ChangeInfo.toJetChangeInfo(
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
@@ -557,21 +560,25 @@ fun ChangeInfo.toJetChangeInfo(
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(
callableDescriptor = functionDescriptor,
originalIndex = oldIndex, originalIndex = oldIndex,
name = info.name, name = info.name,
originalTypeInfo = KotlinTypeInfo(false, parameterType), originalTypeInfo = KotlinTypeInfo(false, parameterType),
defaultValueForCall = defaultValueExpr, defaultValueForCall = defaultValueExpr,
valOrVar = valOrVar).apply { valOrVar = valOrVar
).apply {
currentTypeInfo = KotlinTypeInfo(false, currentType) currentTypeInfo = KotlinTypeInfo(false, currentType)
} }
} }
return KotlinChangeInfo(originalChangeSignatureDescriptor, return KotlinChangeInfo(
originalChangeSignatureDescriptor,
newName, newName,
KotlinTypeInfo(true, functionDescriptor.returnType), KotlinTypeInfo(true, functionDescriptor.returnType),
functionDescriptor.visibility, functionDescriptor.visibility,
newParameters, newParameters,
null, null,
method) method
)
} }
@@ -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
@@ -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()
} }
} }
@@ -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 {
"" ""
} }
@@ -118,8 +122,7 @@ class KotlinChangeSignatureDialog(
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())
@@ -147,8 +150,8 @@ 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
} }
@@ -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)
@@ -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,13 +309,15 @@ class KotlinChangeSignatureDialog(
} }
override fun calculateSignature(): String { override fun calculateSignature(): String {
val changeInfo = evaluateChangeInfo(parametersTableModel, val changeInfo = evaluateChangeInfo(
parametersTableModel,
myReturnTypeCodeFragment, myReturnTypeCodeFragment,
getMethodDescriptor(), getMethodDescriptor(),
visibility, visibility,
methodName, methodName,
myDefaultValueContext, myDefaultValueContext,
true) true
)
return changeInfo.getNewSignature(getMethodDescriptor().originalPrimaryCallable) return changeInfo.getNewSignature(getMethodDescriptor().originalPrimaryCallable)
} }
@@ -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
} }
} }
} }
@@ -382,13 +385,15 @@ class KotlinChangeSignatureDialog(
} }
override fun createRefactoringProcessor(): BaseRefactoringProcessor { override fun createRefactoringProcessor(): BaseRefactoringProcessor {
val changeInfo = evaluateChangeInfo(parametersTableModel, val changeInfo = evaluateChangeInfo(
parametersTableModel,
myReturnTypeCodeFragment, myReturnTypeCodeFragment,
getMethodDescriptor(), getMethodDescriptor(),
visibility, visibility,
methodName, methodName,
myDefaultValueContext, myDefaultValueContext,
false) false
)
changeInfo.primaryPropagationTargets = myMethodsToPropagateParameters ?: emptyList() changeInfo.primaryPropagationTargets = myMethodsToPropagateParameters ?: emptyList()
return KotlinChangeSignatureProcessor(myProject, changeInfo, commandName ?: title) return KotlinChangeSignatureProcessor(myProject, changeInfo, commandName ?: title)
} }
@@ -401,12 +406,15 @@ class KotlinChangeSignatureDialog(
} }
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)
} }
} }
@@ -427,19 +435,23 @@ 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(
project: Project,
commandName: String, commandName: String,
method: KotlinMethodDescriptor, method: KotlinMethodDescriptor,
defaultValueContext: PsiElement): BaseRefactoringProcessor { 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(
parameterTableModel,
createReturnTypeCodeFragment(project, method), createReturnTypeCodeFragment(project, method),
method, method,
method.visibility, method.visibility,
method.name, method.name,
defaultValueContext, defaultValueContext,
false) 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(
parametersModel: KotlinCallableParameterTableModel,
returnTypeCodeFragment: PsiCodeFragment?, returnTypeCodeFragment: PsiCodeFragment?,
methodDescriptor: KotlinMethodDescriptor, methodDescriptor: KotlinMethodDescriptor,
visibility: Visibility?, visibility: Visibility?,
methodName: String, methodName: String,
defaultValueContext: PsiElement, defaultValueContext: PsiElement,
forPreview: Boolean): KotlinChangeInfo { 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(
methodDescriptor.original,
methodName, methodName,
returnTypeCodeFragment.getTypeInfo(true, forPreview), returnTypeCodeFragment.getTypeInfo(true, forPreview),
visibility ?: Visibilities.DEFAULT_VISIBILITY, visibility ?: Visibilities.DEFAULT_VISIBILITY,
parameters, parameters,
parametersModel.receiver, parametersModel.receiver,
defaultValueContext) defaultValueContext
)
} }
} }
} }
@@ -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)) {
@@ -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
@@ -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)
} }
} }
@@ -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) {
@@ -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
@@ -199,8 +196,7 @@ 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)
@@ -209,10 +205,13 @@ class KotlinFunctionCallUsage(
if (argumentExpression == null) continue if (argumentExpression == null) continue
if (needSeparateVariable(argumentExpression) if (needSeparateVariable(argumentExpression)
&& PsiTreeUtil.getNonStrictParentOfType(element, && PsiTreeUtil.getNonStrictParentOfType(
element,
KtConstructorDelegationCall::class.java, KtConstructorDelegationCall::class.java,
KtSuperTypeListEntry::class.java, KtSuperTypeListEntry::class.java,
KtParameter::class.java) == null) { KtParameter::class.java
) == null
) {
KotlinIntroduceVariableHandler.doRefactoring( KotlinIntroduceVariableHandler.doRefactoring(
project, null, argumentExpression, project, null, argumentExpression,
@@ -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!!)
} }
} }
@@ -316,7 +314,11 @@ class KotlinFunctionCallUsage(
} }
} }
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
@@ -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 -> {
@@ -422,15 +423,14 @@ class KotlinFunctionCallUsage(
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(
@@ -455,8 +455,7 @@ class KotlinFunctionCallUsage(
?: 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
@@ -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(
project, replacementStrategy, callable, reference,
inlineThisOnly = isInlineThisOnly, inlineThisOnly = isInlineThisOnly,
deleteAfter = !isInlineThisOnly && !isKeepTheDeclaration, deleteAfter = !isInlineThisOnly && !isKeepTheDeclaration,
statementToDelete = assignmentToDelete) statementToDelete = assignmentToDelete
)
) )
val settings = JavaRefactoringSettings.getInstance() val settings = JavaRefactoringSettings.getInstance()
@@ -30,11 +30,13 @@ 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(
@@ -29,7 +29,7 @@ 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(
@@ -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)) {
@@ -61,20 +61,20 @@ open class ExtractFunctionParameterTablePanel : AbstractParameterTablePanel<Para
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)
@@ -96,7 +96,7 @@ open class ExtractFunctionParameterTablePanel : AbstractParameterTablePanel<Para
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)
} }
@@ -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(),
@@ -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)
} }
} }
@@ -40,7 +40,7 @@ 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) =
@@ -60,8 +60,7 @@ class KotlinIntroducePropertyHandler(
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)
} }
} }
@@ -76,7 +75,8 @@ class KotlinIntroducePropertyHandler(
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
) )
@@ -107,16 +107,14 @@ class KotlinIntroducePropertyHandler(
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,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 }
@@ -90,8 +91,7 @@ fun IntroduceTypeAliasData.analyze(): IntroduceTypeAliasAnalysisResult {
.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,14 +122,11 @@ 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
return when (parent) {
is KtClassBody -> listOf(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD) is KtClassBody -> listOf(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD)
is KtFile -> listOf(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD) is KtFile -> listOf(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD)
else -> emptyList() else -> emptyList()
} }
}
fun IntroduceTypeAliasDescriptor.validate(): IntroduceTypeAliasDescriptorWithConflicts { fun IntroduceTypeAliasDescriptor.validate(): IntroduceTypeAliasDescriptorWithConflicts {
val conflicts = MultiMap<PsiElement, String>() val conflicts = MultiMap<PsiElement, String>()
@@ -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,19 +216,18 @@ 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) }
} }
} }
@@ -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)
@@ -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
@@ -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
@@ -114,7 +116,8 @@ private fun KtDeclaration.processVariableAccesses(
{ {
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 =
kind == AccessKind.WRITE_ONLY || kind == AccessKind.WRITE_WITH_OPTIONAL_READ || kind == AccessKind.READ_OR_WRITE
isReadWriteAccess = kind == AccessKind.WRITE_WITH_OPTIONAL_READ || kind == AccessKind.READ_OR_WRITE isReadWriteAccess = kind == AccessKind.WRITE_WITH_OPTIONAL_READ || kind == AccessKind.READ_OR_WRITE
isSearchForTextOccurrences = false isSearchForTextOccurrences = false
isSkipImportStatements = true isSkipImportStatements = true
@@ -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
} }
} }
} }
@@ -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
} }
} }
@@ -193,7 +196,7 @@ 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,12 +251,13 @@ 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
@@ -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
@@ -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()
} }
} }
@@ -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()
} }
} }
@@ -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 -> {
}
} }
} }
} }
@@ -64,7 +64,7 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention<KtNamedDeclaration
return TextRange( return TextRange(
element.startOffset, element.startOffset,
element.getSuperTypeList()?.startOffset ?: element.getBody()?.startOffset ?: element.endOffset element.getSuperTypeList()?.startOffset ?: element.body?.startOffset ?: element.endOffset
) )
} }
@@ -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)
@@ -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) {
@@ -176,12 +178,11 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention<KtNamedDeclaration
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
} }
} }
} }