Extract Function: Make compliant with PublicApiImplicitTypeInspection

This commit is contained in:
Alexey Sedunov
2018-06-07 20:15:48 +03:00
parent 633c67ebf0
commit ed597e2da5
4 changed files with 49 additions and 15 deletions
@@ -23,6 +23,8 @@ import com.intellij.psi.*
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.lexer.KotlinLexer
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
@@ -33,6 +35,7 @@ import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import java.lang.IllegalArgumentException
import java.util.*
// NOTE: in this file we collect only Kotlin-specific methods working with PSI and not modifying it
@@ -593,4 +596,14 @@ fun isTopLevelInFileOrScript(element: PsiElement): Boolean {
is KtBlockExpression -> parent.parent is KtScript
else -> false
}
}
fun KtModifierKeywordToken.toVisibility(): Visibility {
return when (this) {
KtTokens.PUBLIC_KEYWORD -> Visibilities.PUBLIC
KtTokens.PRIVATE_KEYWORD -> Visibilities.PRIVATE
KtTokens.PROTECTED_KEYWORD -> Visibilities.PROTECTED
KtTokens.INTERNAL_KEYWORD -> Visibilities.INTERNAL
else -> throw IllegalArgumentException("Unknown visibility modifier:$this")
}
}
@@ -22,7 +22,6 @@ import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.core.canBePrivate
import org.jetbrains.kotlin.idea.core.canBeProtected
import org.jetbrains.kotlin.idea.core.setVisibility
@@ -31,9 +30,9 @@ import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi.psiUtil.toVisibility
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
import java.lang.IllegalArgumentException
open class ChangeVisibilityModifierIntention protected constructor(
val modifier: KtModifierKeywordToken
@@ -88,16 +87,6 @@ open class ChangeVisibilityModifierIntention protected constructor(
if (element is KtPropertyAccessor) element.modifierList?.nextSibling?.replace(KtPsiFactory(element).createWhiteSpace())
}
private fun KtModifierKeywordToken.toVisibility(): Visibility {
return when (this) {
KtTokens.PUBLIC_KEYWORD -> Visibilities.PUBLIC
KtTokens.PRIVATE_KEYWORD -> Visibilities.PRIVATE
KtTokens.PROTECTED_KEYWORD -> Visibilities.PROTECTED
KtTokens.INTERNAL_KEYWORD -> Visibilities.INTERNAL
else -> throw IllegalArgumentException("Unknown visibility modifier:$this")
}
}
private fun noModifierYetApplicabilityRange(declaration: KtDeclaration): TextRange? {
return when (declaration) {
is KtNamedFunction -> declaration.funKeyword?.textRange
@@ -607,9 +607,13 @@ private fun ExtractionData.getLocalInstructions(pseudocode: Pseudocode): List<In
return instructions
}
fun ExtractionData.isVisibilityApplicable(): Boolean {
fun ExtractionData.isLocal(): Boolean {
val parent = targetSibling.parent
if (parent !is KtClassBody && (parent !is KtFile || parent.isScript())) return false
return parent !is KtClassBody && (parent !is KtFile || parent.isScript())
}
fun ExtractionData.isVisibilityApplicable(): Boolean {
if (isLocal()) return false
if (commonParent.parentsWithSelf.any { it is KtNamedFunction && it.hasModifier(KtTokens.INLINE_KEYWORD) && it.isPublic }) return false
return true
}
@@ -16,7 +16,9 @@
package org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine
import com.intellij.codeHighlighting.HighlightDisplayLevel
import com.intellij.openapi.util.Key
import com.intellij.profile.codeInspection.ProjectInspectionProfileManager
import com.intellij.psi.PsiElement
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.search.LocalSearchScope
@@ -24,7 +26,9 @@ import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.refactoring.BaseRefactoringProcessor
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.idea.core.*
import org.jetbrains.kotlin.idea.inspections.PublicApiImplicitTypeInspection
import org.jetbrains.kotlin.idea.inspections.UseExpressionBodyInspection
import org.jetbrains.kotlin.idea.intentions.InfixCallToOrdinaryIntention
import org.jetbrains.kotlin.idea.intentions.OperatorToFunctionIntention
@@ -38,6 +42,7 @@ import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.psi.patternMatching.*
import org.jetbrains.kotlin.idea.util.psi.patternMatching.UnificationResult.StronglyMatched
import org.jetbrains.kotlin.idea.util.psi.patternMatching.UnificationResult.WeaklyMatched
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtPsiFactory.CallableBuilder
import org.jetbrains.kotlin.psi.codeFragmentUtil.DEBUG_TYPE_REFERENCE_STRING
@@ -456,6 +461,29 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
}
}
fun getPublicApiInspectionIfEnabled(): PublicApiImplicitTypeInspection? {
val project = descriptor.extractionData.project
val inspectionProfileManager = ProjectInspectionProfileManager.getInstance(project)
val inspectionProfile = inspectionProfileManager.currentProfile
val state = inspectionProfile.getToolsOrNull("PublicApiImplicitType", project)?.defaultState ?: return null
if (!state.isEnabled || state.level == HighlightDisplayLevel.DO_NOT_SHOW) return null
return state.tool.tool as? PublicApiImplicitTypeInspection
}
fun useExplicitReturnType(): Boolean {
if (descriptor.returnType.isFlexible()) return true
val inspection = getPublicApiInspectionIfEnabled() ?: return false
val targetClass = (descriptor.extractionData.targetSibling.parent as? KtClassBody)?.parent as? KtClassOrObject
if ((targetClass != null && targetClass.isLocal) || descriptor.extractionData.isLocal()) return false
val visibility = (descriptor.visibility ?: KtTokens.DEFAULT_VISIBILITY_KEYWORD).toVisibility()
return when {
visibility.isPublicAPI -> true
inspection.reportInternal && visibility == Visibilities.INTERNAL -> true
inspection.reportPrivate && visibility == Visibilities.PRIVATE -> true
else -> false
}
}
fun adjustDeclarationBody(declaration: KtNamedDeclaration) {
val body = declaration.getGeneratedBody()
@@ -554,7 +582,7 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
val bodyOwner = body.parent as KtDeclarationWithBody
val useExpressionBodyInspection = UseExpressionBodyInspection()
if (bodyExpression != null && !bodyExpression.isMultiLine() && useExpressionBodyInspection.isActiveFor(bodyOwner)) {
useExpressionBodyInspection.simplify(bodyOwner, !descriptor.returnType.isFlexible())
useExpressionBodyInspection.simplify(bodyOwner, !useExplicitReturnType())
}
}
}