J2k post-processings based on diagnostics are included into the common scheme
This commit is contained in:
@@ -16,14 +16,23 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.j2k
|
package org.jetbrains.kotlin.idea.j2k
|
||||||
|
|
||||||
|
import com.intellij.psi.search.LocalSearchScope
|
||||||
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.idea.intentions.*
|
import org.jetbrains.kotlin.idea.intentions.*
|
||||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToElvisIntention
|
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToElvisIntention
|
||||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToSafeAccessIntention
|
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToSafeAccessIntention
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.RemoveRightPartOfBinaryExpressionFix
|
||||||
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
interface J2kPostProcessing {
|
interface J2kPostProcessing {
|
||||||
fun createAction(element: JetElement): (() -> Unit)?
|
fun createAction(element: JetElement, diagnostics: Diagnostics): (() -> Unit)?
|
||||||
}
|
}
|
||||||
|
|
||||||
object J2KPostProcessingRegistrar {
|
object J2KPostProcessingRegistrar {
|
||||||
@@ -37,19 +46,51 @@ object J2KPostProcessingRegistrar {
|
|||||||
_processings.add(MoveLambdaOutsideParenthesesProcessing())
|
_processings.add(MoveLambdaOutsideParenthesesProcessing())
|
||||||
_processings.add(ConvertToStringTemplateProcessing())
|
_processings.add(ConvertToStringTemplateProcessing())
|
||||||
|
|
||||||
registerTypicalIntentionBasedProcessing(UsePropertyAccessSyntaxIntention()) { applyTo(it) }
|
registerIntentionBasedProcessing(UsePropertyAccessSyntaxIntention()) { applyTo(it) }
|
||||||
registerTypicalIntentionBasedProcessing(IfThenToSafeAccessIntention()) { applyTo(it) }
|
registerIntentionBasedProcessing(IfThenToSafeAccessIntention()) { applyTo(it) }
|
||||||
registerTypicalIntentionBasedProcessing(IfThenToElvisIntention()) { applyTo(it) }
|
registerIntentionBasedProcessing(IfThenToElvisIntention()) { applyTo(it) }
|
||||||
registerTypicalIntentionBasedProcessing(IfNullToElvisIntention()) { applyTo(it) }
|
registerIntentionBasedProcessing(IfNullToElvisIntention()) { applyTo(it) }
|
||||||
registerTypicalIntentionBasedProcessing(SimplifyNegatedBinaryExpressionIntention()) { applyTo(it) }
|
registerIntentionBasedProcessing(SimplifyNegatedBinaryExpressionIntention()) { applyTo(it) }
|
||||||
|
|
||||||
|
registerDiagnosticBasedProcessing<JetBinaryExpressionWithTypeRHS>(Errors.USELESS_CAST) { element, diagnostic ->
|
||||||
|
val expression = RemoveRightPartOfBinaryExpressionFix(element, "").invoke()
|
||||||
|
|
||||||
|
val variable = expression.parent as? JetProperty
|
||||||
|
if (variable != null && expression == variable.initializer && variable.isLocal) {
|
||||||
|
val refs = ReferencesSearch.search(variable, LocalSearchScope(variable.containingFile)).findAll()
|
||||||
|
for (ref in refs) {
|
||||||
|
val usage = ref.element as? JetSimpleNameExpression ?: continue
|
||||||
|
usage.replace(expression)
|
||||||
|
}
|
||||||
|
variable.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registerDiagnosticBasedProcessing<JetTypeProjection>(Errors.REDUNDANT_PROJECTION) { element, diagnostic ->
|
||||||
|
val fix = RemoveModifierFix.createRemoveProjectionFactory(true).createActions(diagnostic).single() as RemoveModifierFix
|
||||||
|
fix.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
registerDiagnosticBasedProcessing<JetSimpleNameExpression>(Errors.UNNECESSARY_NOT_NULL_ASSERTION) { element, diagnostic ->
|
||||||
|
val exclExclExpr = element.parent as JetUnaryExpression
|
||||||
|
exclExclExpr.replace(exclExclExpr.baseExpression!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
registerDiagnosticBasedProcessing<JetSimpleNameExpression>(Errors.VAL_REASSIGNMENT) { element, diagnostic ->
|
||||||
|
val property = element.mainReference.resolve() as? JetProperty
|
||||||
|
if (property != null && !property.isVar) {
|
||||||
|
val factory = JetPsiFactory(element.project)
|
||||||
|
property.valOrVarKeyword.replace(factory.createVarKeyword())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified TElement : JetElement, TIntention: JetSelfTargetingRangeIntention<TElement>> registerTypicalIntentionBasedProcessing(
|
private inline fun <reified TElement : JetElement, TIntention: JetSelfTargetingRangeIntention<TElement>> registerIntentionBasedProcessing(
|
||||||
intention: TIntention,
|
intention: TIntention,
|
||||||
inlineOptions(InlineOption.ONLY_LOCAL_RETURN) apply: TIntention.(TElement) -> Unit
|
inlineOptions(InlineOption.ONLY_LOCAL_RETURN) apply: TIntention.(TElement) -> Unit
|
||||||
) {
|
) {
|
||||||
_processings.add(object : J2kPostProcessing {
|
_processings.add(object : J2kPostProcessing {
|
||||||
override fun createAction(element: JetElement): (() -> Unit)? {
|
override fun createAction(element: JetElement, diagnostics: Diagnostics): (() -> Unit)? {
|
||||||
if (!javaClass<TElement>().isInstance(element)) return null
|
if (!javaClass<TElement>().isInstance(element)) return null
|
||||||
@suppress("UNCHECKED_CAST")
|
@suppress("UNCHECKED_CAST")
|
||||||
if (intention.applicabilityRange(element as TElement) == null) return null
|
if (intention.applicabilityRange(element as TElement) == null) return null
|
||||||
@@ -58,8 +99,21 @@ object J2KPostProcessingRegistrar {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun <reified TElement : JetElement> registerDiagnosticBasedProcessing(
|
||||||
|
diagnosticFactory: DiagnosticFactory<*>,
|
||||||
|
inlineOptions(InlineOption.ONLY_LOCAL_RETURN) fix: (TElement, Diagnostic) -> Unit
|
||||||
|
) {
|
||||||
|
_processings.add(object : J2kPostProcessing {
|
||||||
|
override fun createAction(element: JetElement, diagnostics: Diagnostics): (() -> Unit)? {
|
||||||
|
if (!javaClass<TElement>().isInstance(element)) return null
|
||||||
|
val diagnostic = diagnostics.forElement(element).firstOrNull { it.factory == diagnosticFactory } ?: return null
|
||||||
|
return { fix(element as TElement, diagnostic) }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private class RemoveExplicitTypeArgumentsProcessing : J2kPostProcessing {
|
private class RemoveExplicitTypeArgumentsProcessing : J2kPostProcessing {
|
||||||
override fun createAction(element: JetElement): (() -> Unit)? {
|
override fun createAction(element: JetElement, diagnostics: Diagnostics): (() -> Unit)? {
|
||||||
if (element !is JetTypeArgumentList || !RemoveExplicitTypeArgumentsIntention.isApplicableTo(element, approximateFlexible = true)) return null
|
if (element !is JetTypeArgumentList || !RemoveExplicitTypeArgumentsIntention.isApplicableTo(element, approximateFlexible = true)) return null
|
||||||
|
|
||||||
return { element.delete() }
|
return { element.delete() }
|
||||||
@@ -69,7 +123,7 @@ object J2KPostProcessingRegistrar {
|
|||||||
private class MoveLambdaOutsideParenthesesProcessing : J2kPostProcessing {
|
private class MoveLambdaOutsideParenthesesProcessing : J2kPostProcessing {
|
||||||
private val intention = MoveLambdaOutsideParenthesesIntention()
|
private val intention = MoveLambdaOutsideParenthesesIntention()
|
||||||
|
|
||||||
override fun createAction(element: JetElement): (() -> Unit)? {
|
override fun createAction(element: JetElement, diagnostics: Diagnostics): (() -> Unit)? {
|
||||||
if (element !is JetCallExpression) return null
|
if (element !is JetCallExpression) return null
|
||||||
val literalArgument = element.valueArguments.lastOrNull()?.getArgumentExpression()?.unpackFunctionLiteral() ?: return null
|
val literalArgument = element.valueArguments.lastOrNull()?.getArgumentExpression()?.unpackFunctionLiteral() ?: return null
|
||||||
if (!intention.isApplicableTo(element, literalArgument.textOffset)) return null
|
if (!intention.isApplicableTo(element, literalArgument.textOffset)) return null
|
||||||
@@ -80,7 +134,7 @@ object J2KPostProcessingRegistrar {
|
|||||||
private class ConvertToStringTemplateProcessing : J2kPostProcessing {
|
private class ConvertToStringTemplateProcessing : J2kPostProcessing {
|
||||||
private val intention = ConvertToStringTemplateIntention()
|
private val intention = ConvertToStringTemplateIntention()
|
||||||
|
|
||||||
override fun createAction(element: JetElement): (() -> Unit)? {
|
override fun createAction(element: JetElement, diagnostics: Diagnostics): (() -> Unit)? {
|
||||||
if (element is JetBinaryExpression && intention.isApplicableTo(element) && intention.isConversionResultSimple(element)) {
|
if (element is JetBinaryExpression && intention.isApplicableTo(element) && intention.isConversionResultSimple(element)) {
|
||||||
return { intention.applyTo(element) }
|
return { intention.applyTo(element) }
|
||||||
}
|
}
|
||||||
@@ -89,5 +143,4 @@ object J2KPostProcessingRegistrar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -21,66 +21,23 @@ import com.intellij.openapi.util.TextRange
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiRecursiveElementVisitor
|
import com.intellij.psi.PsiRecursiveElementVisitor
|
||||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||||
import com.intellij.psi.search.LocalSearchScope
|
|
||||||
import com.intellij.psi.search.searches.ReferencesSearch
|
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||||
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
|
import org.jetbrains.kotlin.idea.conversion.copy.range
|
||||||
import org.jetbrains.kotlin.idea.quickfix.RemoveRightPartOfBinaryExpressionFix
|
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
|
||||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||||
import org.jetbrains.kotlin.j2k.PostProcessor
|
import org.jetbrains.kotlin.j2k.PostProcessor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.JetElement
|
||||||
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
import java.util.HashSet
|
|
||||||
import java.util.LinkedHashMap
|
import java.util.LinkedHashMap
|
||||||
|
|
||||||
public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
||||||
override fun analyzeFile(file: JetFile, range: TextRange?): BindingContext {
|
|
||||||
val elements = if (range == null) {
|
|
||||||
listOf(file)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
file.elementsInRange(range).filterIsInstance<JetElement>()
|
|
||||||
}
|
|
||||||
if (elements.isEmpty()) return BindingContext.EMPTY
|
|
||||||
return file.getResolutionFacade().analyzeFullyAndGetResult(elements).bindingContext
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun insertImport(file: JetFile, fqName: FqName) {
|
override fun insertImport(file: JetFile, fqName: FqName) {
|
||||||
val descriptors = file.resolveImportReference(fqName)
|
val descriptors = file.resolveImportReference(fqName)
|
||||||
descriptors.firstOrNull()?.let { ImportInsertHelper.getInstance(file.getProject()).importDescriptor(file, it) }
|
descriptors.firstOrNull()?.let { ImportInsertHelper.getInstance(file.project).importDescriptor(file, it) }
|
||||||
}
|
|
||||||
|
|
||||||
override fun fixForProblem(problem: Diagnostic): (() -> Unit)? {
|
|
||||||
val psiElement = problem.getPsiElement()
|
|
||||||
return when (problem.getFactory()) {
|
|
||||||
Errors.USELESS_CAST -> { ->
|
|
||||||
val expression = RemoveRightPartOfBinaryExpressionFix(psiElement as JetBinaryExpressionWithTypeRHS, "").invoke()
|
|
||||||
|
|
||||||
val variable = expression.getParent() as? JetProperty
|
|
||||||
if (variable != null && expression == variable.getInitializer() && variable.isLocal()) {
|
|
||||||
val refs = ReferencesSearch.search(variable, LocalSearchScope(variable.getContainingFile())).findAll()
|
|
||||||
for (ref in refs) {
|
|
||||||
val usage = ref.getElement() as? JetSimpleNameExpression ?: continue
|
|
||||||
usage.replace(expression)
|
|
||||||
}
|
|
||||||
variable.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Errors.REDUNDANT_PROJECTION -> { ->
|
|
||||||
val fix = RemoveModifierFix.createRemoveProjectionFactory(true).createActions(problem).single() as RemoveModifierFix
|
|
||||||
fix.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> super.fixForProblem(problem)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum class RangeFilterResult {
|
private enum class RangeFilterResult {
|
||||||
@@ -93,7 +50,7 @@ public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
var elementToActions = collectAvailableActions(file, rangeMarker)
|
var elementToActions = collectAvailableActions(file, rangeMarker)
|
||||||
|
|
||||||
while (elementToActions.isNotEmpty()) {
|
while (elementToActions.isNotEmpty()) {
|
||||||
val processingsToRerun = HashSet<J2kPostProcessing>()
|
var modificationStamp: Long? = file.modificationStamp
|
||||||
|
|
||||||
for ((element, actions) in elementToActions) {
|
for ((element, actions) in elementToActions) {
|
||||||
for ((action, processing) in actions) {
|
for ((action, processing) in actions) {
|
||||||
@@ -101,21 +58,21 @@ public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
action()
|
action()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
processingsToRerun.add(processing)
|
modificationStamp = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (processingsToRerun.isEmpty()) break
|
if (modificationStamp == file.modificationStamp) break
|
||||||
//TODO: it looks like there are no such cases currently, add tests later on or drop this
|
|
||||||
elementToActions = collectAvailableActions(file, rangeMarker, processingFilter = { it in processingsToRerun })
|
elementToActions = collectAvailableActions(file, rangeMarker)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formatCode) {
|
if (formatCode) {
|
||||||
val codeStyleManager = CodeStyleManager.getInstance(file.getProject())
|
val codeStyleManager = CodeStyleManager.getInstance(file.project)
|
||||||
if (rangeMarker != null) {
|
if (rangeMarker != null) {
|
||||||
if (rangeMarker.isValid()) {
|
if (rangeMarker.isValid) {
|
||||||
codeStyleManager.reformatRange(file, rangeMarker.getStartOffset(), rangeMarker.getEndOffset())
|
codeStyleManager.reformatRange(file, rangeMarker.startOffset, rangeMarker.endOffset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -126,12 +83,9 @@ public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
|
|
||||||
private data class ActionData(val action: () -> Unit, val processing: J2kPostProcessing)
|
private data class ActionData(val action: () -> Unit, val processing: J2kPostProcessing)
|
||||||
|
|
||||||
private fun collectAvailableActions(
|
private fun collectAvailableActions(file: JetFile, rangeMarker: RangeMarker?): LinkedHashMap<JetElement, SmartList<ActionData>> {
|
||||||
file: JetFile,
|
val diagnostics = analyzeFileRange(file, rangeMarker)
|
||||||
rangeMarker: RangeMarker?,
|
|
||||||
processingFilter: (J2kPostProcessing) -> Boolean = { true }
|
|
||||||
): LinkedHashMap<JetElement, SmartList<ActionData>> {
|
|
||||||
val processings = J2KPostProcessingRegistrar.processings.filter(processingFilter)
|
|
||||||
val elementToActions = LinkedHashMap<JetElement, SmartList<ActionData>>()
|
val elementToActions = LinkedHashMap<JetElement, SmartList<ActionData>>()
|
||||||
|
|
||||||
file.accept(object : PsiRecursiveElementVisitor(){
|
file.accept(object : PsiRecursiveElementVisitor(){
|
||||||
@@ -143,8 +97,8 @@ public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
super.visitElement(element)
|
super.visitElement(element)
|
||||||
|
|
||||||
if (rangeResult == RangeFilterResult.PROCESS) {
|
if (rangeResult == RangeFilterResult.PROCESS) {
|
||||||
processings.forEach { processing ->
|
J2KPostProcessingRegistrar.processings.forEach { processing ->
|
||||||
val action = processing.createAction(element)
|
val action = processing.createAction(element, diagnostics)
|
||||||
if (action != null) {
|
if (action != null) {
|
||||||
elementToActions.getOrPut(element) { SmartList() }.add(ActionData(action, processing))
|
elementToActions.getOrPut(element) { SmartList() }.add(ActionData(action, processing))
|
||||||
}
|
}
|
||||||
@@ -157,6 +111,18 @@ public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
return elementToActions
|
return elementToActions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun analyzeFileRange(file: JetFile, rangeMarker: RangeMarker?): Diagnostics {
|
||||||
|
val elements = if (rangeMarker == null)
|
||||||
|
listOf(file)
|
||||||
|
else
|
||||||
|
file.elementsInRange(rangeMarker.range!!).filterIsInstance<JetElement>()
|
||||||
|
|
||||||
|
return if (elements.isNotEmpty())
|
||||||
|
file.getResolutionFacade().analyzeFullyAndGetResult(elements).bindingContext.diagnostics
|
||||||
|
else
|
||||||
|
Diagnostics.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
private fun rangeFilter(element: PsiElement, rangeMarker: RangeMarker?): RangeFilterResult {
|
private fun rangeFilter(element: PsiElement, rangeMarker: RangeMarker?): RangeFilterResult {
|
||||||
if (rangeMarker == null) return RangeFilterResult.PROCESS
|
if (rangeMarker == null) return RangeFilterResult.PROCESS
|
||||||
if (!rangeMarker.isValid) return RangeFilterResult.SKIP
|
if (!rangeMarker.isValid) return RangeFilterResult.SKIP
|
||||||
@@ -168,6 +134,4 @@ public class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
else -> RangeFilterResult.SKIP
|
else -> RangeFilterResult.SKIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun simpleNameReference(nameExpression: JetSimpleNameExpression) = nameExpression.mainReference
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,44 +18,21 @@ package org.jetbrains.kotlin.j2k
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
|
|
||||||
public class AfterConversionPass(val project: Project, val postProcessor: PostProcessor) {
|
public class AfterConversionPass(val project: Project, val postProcessor: PostProcessor) {
|
||||||
public fun run(kotlinFile: JetFile, range: TextRange?) {
|
public fun run(kotlinFile: JetFile, range: TextRange?) {
|
||||||
val bindingContext = postProcessor.analyzeFile(kotlinFile, range)
|
|
||||||
|
|
||||||
fun fixForProblem(diagnostic: Diagnostic): (() -> Unit)? {
|
|
||||||
val psiElement = diagnostic.getPsiElement()
|
|
||||||
if (range != null && psiElement.getTextRange() !in range) return null
|
|
||||||
return postProcessor.fixForProblem(diagnostic)
|
|
||||||
}
|
|
||||||
|
|
||||||
val fixes = bindingContext.getDiagnostics()
|
|
||||||
.map {
|
|
||||||
val fix = fixForProblem(it)
|
|
||||||
if (fix != null) Pair(it.getPsiElement(), fix) else null
|
|
||||||
}
|
|
||||||
.filterNotNull()
|
|
||||||
|
|
||||||
val rangeMarker = if (range != null) {
|
val rangeMarker = if (range != null) {
|
||||||
val document = kotlinFile.getViewProvider().getDocument()!!
|
val document = kotlinFile.viewProvider.document!!
|
||||||
val marker = document.createRangeMarker(range.getStartOffset(), range.getEndOffset())
|
val marker = document.createRangeMarker(range.startOffset, range.endOffset)
|
||||||
marker.setGreedyToLeft(true)
|
marker.isGreedyToLeft = true
|
||||||
marker.setGreedyToRight(true)
|
marker.isGreedyToRight = true
|
||||||
marker
|
marker
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((psiElement, fix) in fixes) {
|
|
||||||
if (psiElement.isValid()) {
|
|
||||||
fix()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
postProcessor.doAdditionalProcessing(kotlinFile, rangeMarker)
|
postProcessor.doAdditionalProcessing(kotlinFile, rangeMarker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,59 +17,28 @@
|
|||||||
package org.jetbrains.kotlin.j2k
|
package org.jetbrains.kotlin.j2k
|
||||||
|
|
||||||
import com.intellij.lang.java.JavaLanguage
|
import com.intellij.lang.java.JavaLanguage
|
||||||
import com.intellij.openapi.application.ModalityState
|
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.editor.RangeMarker
|
import com.intellij.openapi.editor.RangeMarker
|
||||||
import com.intellij.openapi.progress.*
|
import com.intellij.openapi.progress.*
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.TextRange
|
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.source.DummyHolder
|
import com.intellij.psi.impl.source.DummyHolder
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
|
||||||
import org.jetbrains.kotlin.idea.JetLanguage
|
import org.jetbrains.kotlin.idea.JetLanguage
|
||||||
import org.jetbrains.kotlin.j2k.ast.Element
|
import org.jetbrains.kotlin.j2k.ast.Element
|
||||||
import org.jetbrains.kotlin.j2k.usageProcessing.UsageProcessing
|
import org.jetbrains.kotlin.j2k.usageProcessing.UsageProcessing
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
|
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.Comparator
|
import java.util.Comparator
|
||||||
import java.util.LinkedHashMap
|
import java.util.LinkedHashMap
|
||||||
|
|
||||||
public interface PostProcessor {
|
public interface PostProcessor {
|
||||||
public fun analyzeFile(file: JetFile, range: TextRange?): BindingContext
|
|
||||||
|
|
||||||
public fun insertImport(file: JetFile, fqName: FqName)
|
public fun insertImport(file: JetFile, fqName: FqName)
|
||||||
|
|
||||||
public open fun fixForProblem(problem: Diagnostic): (() -> Unit)? {
|
|
||||||
val psiElement = problem.getPsiElement()
|
|
||||||
return when (problem.getFactory()) {
|
|
||||||
Errors.UNNECESSARY_NOT_NULL_ASSERTION -> { ->
|
|
||||||
val exclExclOp = psiElement as JetSimpleNameExpression
|
|
||||||
val exclExclExpr = exclExclOp.getParent() as JetUnaryExpression
|
|
||||||
exclExclExpr.replace(exclExclExpr.getBaseExpression()!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
Errors.VAL_REASSIGNMENT -> { ->
|
|
||||||
if (psiElement is JetSimpleNameExpression) {
|
|
||||||
val property = simpleNameReference(psiElement).resolve() as? JetProperty
|
|
||||||
if (property != null && !property.isVar()) {
|
|
||||||
val factory = JetPsiFactory(psiElement.getProject())
|
|
||||||
property.getValOrVarKeyword().replace(factory.createVarKeyword())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun doAdditionalProcessing(file: JetFile, rangeMarker: RangeMarker?)
|
public fun doAdditionalProcessing(file: JetFile, rangeMarker: RangeMarker?)
|
||||||
|
|
||||||
public fun simpleNameReference(nameExpression: JetSimpleNameExpression): PsiReference
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum class ParseContext {
|
public enum class ParseContext {
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ public object Test {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val result = true
|
val result = true
|
||||||
if (parent.isDirectory()) {
|
if (parent.isDirectory) {
|
||||||
return true
|
return true
|
||||||
} else
|
} else
|
||||||
return false
|
return false
|
||||||
|
|||||||
Reference in New Issue
Block a user