mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[extract method] decouple settings from the extract template
GitOrigin-RevId: a628ca0ecfa302e9920c315e7adacc14471b6053
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1c8daa89b7
commit
13a49ea232
+33
@@ -5,11 +5,14 @@ import com.intellij.codeInsight.Nullability
|
||||
import com.intellij.codeInsight.NullableNotNullManager
|
||||
import com.intellij.codeInsight.PsiEquivalenceUtil
|
||||
import com.intellij.codeInsight.intention.AddAnnotationPsiFix
|
||||
import com.intellij.codeInsight.template.impl.TemplateState
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.command.impl.FinishMarkAction
|
||||
import com.intellij.openapi.command.impl.StartMarkAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.impl.EditorImpl
|
||||
import com.intellij.openapi.util.Conditions
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.NlsContexts.Command
|
||||
@@ -30,6 +33,9 @@ import com.intellij.refactoring.extractMethod.newImpl.structures.ExtractOptions
|
||||
import com.intellij.refactoring.extractMethod.newImpl.structures.InputParameter
|
||||
import com.intellij.refactoring.introduceField.ElementToWorkOn
|
||||
import com.intellij.util.CommonJavaRefactoringUtil
|
||||
import com.intellij.util.concurrency.annotations.RequiresWriteLock
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
object ExtractMethodHelper {
|
||||
|
||||
@@ -303,4 +309,31 @@ object ExtractMethodHelper {
|
||||
}
|
||||
|
||||
private data class PsiRange(val parent: PsiElement, val firstChild: PsiElement, val lastChild: PsiElement)
|
||||
|
||||
@RequiresWriteLock
|
||||
fun renameTemplate(templateState: TemplateState?, name: String) {
|
||||
if (templateState == null) return
|
||||
val range = templateState.currentVariableRange ?: return
|
||||
templateState.editor.document.replaceString(range.startOffset, range.endOffset, name)
|
||||
templateState.update()
|
||||
}
|
||||
|
||||
internal suspend fun runWithDumbEditor(editor: Editor, action: suspend () -> Unit) {
|
||||
val editorImpl = editor as? EditorImpl
|
||||
if (editorImpl == null) {
|
||||
action.invoke()
|
||||
return
|
||||
}
|
||||
withContext(Dispatchers.EDT) {
|
||||
editorImpl.startDumb()
|
||||
}
|
||||
try {
|
||||
action.invoke()
|
||||
}
|
||||
finally {
|
||||
withContext(Dispatchers.EDT) {
|
||||
editor.stopDumbLater()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
-5
@@ -2,12 +2,15 @@
|
||||
package com.intellij.refactoring.extractMethod.newImpl
|
||||
|
||||
import com.intellij.codeInsight.Nullability
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
|
||||
import com.intellij.codeInsight.template.impl.TemplateState
|
||||
import com.intellij.ide.util.PropertiesComponent
|
||||
import com.intellij.java.refactoring.JavaRefactoringBundle
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.WriteAction
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.command.writeCommandAction
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
|
||||
@@ -22,11 +25,14 @@ import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.extractMethod.ExtractMethodDialog
|
||||
import com.intellij.refactoring.extractMethod.ExtractMethodHandler
|
||||
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodHelper.guessMethodName
|
||||
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodHelper.renameTemplate
|
||||
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodHelper.replaceWithMethod
|
||||
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodHelper.runWithDumbEditor
|
||||
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodPipeline.findAllOptionsToExtract
|
||||
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodPipeline.selectOptionWithTargetClass
|
||||
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodPipeline.withFilteredAnnotations
|
||||
import com.intellij.refactoring.extractMethod.newImpl.inplace.*
|
||||
import com.intellij.refactoring.extractMethod.newImpl.inplace.InplaceExtractMethodCollector
|
||||
import com.intellij.refactoring.extractMethod.newImpl.inplace.InplaceExtractUtils.createGreedyRangeMarker
|
||||
import com.intellij.refactoring.extractMethod.newImpl.parameterObject.ResultObjectExtractor
|
||||
import com.intellij.refactoring.extractMethod.newImpl.structures.ExtractOptions
|
||||
@@ -46,14 +52,51 @@ data class ExtractedElements(val callElements: List<PsiElement>, val method: Psi
|
||||
|
||||
class MethodExtractor {
|
||||
|
||||
internal fun restartInDialog(templateState: TemplateState, extractor: DuplicatesMethodExtractor, isLinkUsed: Boolean = false) {
|
||||
val editor = templateState.editor
|
||||
val project = templateState.project
|
||||
val methodRange = templateState.currentVariableRange
|
||||
val methodName = if (methodRange != null) editor.document.getText(methodRange) else ""
|
||||
InplaceExtractMethodCollector.openExtractDialog.log(project, isLinkUsed)
|
||||
TemplateManagerImpl.getTemplateState(editor)?.gotoEnd(true)
|
||||
val extractOptions = extractor.extractOptions.copy(methodName = methodName)
|
||||
val rangeToReplace = createGreedyRangeMarker(editor.document, extractor.rangeToReplaceOriginal)
|
||||
val extractor = DuplicatesMethodExtractor(extractOptions, extractor.targetClass, rangeToReplace)
|
||||
extractor.extractInDialog()
|
||||
}
|
||||
|
||||
internal suspend fun restartInplace(templateState: TemplateState, defaultExtractor: DuplicatesMethodExtractor, popup: ExtractMethodPopupProvider) {
|
||||
val startTime = System.currentTimeMillis()
|
||||
|
||||
val editor = templateState.editor
|
||||
val project = templateState.project
|
||||
val methodRange = templateState.currentVariableRange
|
||||
val methodName = if (methodRange != null) editor.document.getText(methodRange) else ""
|
||||
|
||||
runWithDumbEditor(editor) {
|
||||
withContext(Dispatchers.EDT) {
|
||||
TemplateManagerImpl.getTemplateState(editor)?.gotoEnd(true)
|
||||
}
|
||||
val inplaceExtractor = readAction { InplaceMethodExtractor(editor, popup, defaultExtractor) }
|
||||
inplaceExtractor.extractAndRunTemplate(emptyList())
|
||||
val newTemplateState = TemplateManagerImpl.getTemplateState(editor)
|
||||
writeCommandAction(project, ExtractMethodHandler.getRefactoringName()) {
|
||||
renameTemplate(newTemplateState, methodName)
|
||||
}
|
||||
}
|
||||
val endTime = System.currentTimeMillis()
|
||||
InplaceExtractMethodCollector.previewUpdated.log(endTime - startTime)
|
||||
}
|
||||
|
||||
fun doExtract(file: PsiFile, range: TextRange) {
|
||||
if (!CommonRefactoringUtil.checkReadOnlyStatus(file.project, file)) return
|
||||
val coroutineScope = ExtractMethodService.getInstance(file.project).scope
|
||||
|
||||
val editor = PsiEditorUtil.findEditor(file) ?: return
|
||||
val activeExtractor = InplaceMethodExtractor.getActiveExtractor(editor)
|
||||
if (activeExtractor != null) {
|
||||
activeExtractor.restartInDialog()
|
||||
val template = TemplateManagerImpl.getTemplateState(editor)
|
||||
if (activeExtractor != null && template != null) {
|
||||
restartInDialog(template, activeExtractor.extractor, false)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -107,7 +150,7 @@ class MethodExtractor {
|
||||
}
|
||||
if (EditorSettingsExternalizable.getInstance().isVariableInplaceRenameEnabled) {
|
||||
val templateStart = System.currentTimeMillis()
|
||||
runInplaceExtract(editor, range, extractor, guessedNames)
|
||||
runInplaceExtract(editor, extractor, guessedNames)
|
||||
val prepareTemplateTime = System.currentTimeMillis() - templateStart
|
||||
reportPerformanceStatistics(preparePlacesTime, prepareTemplateTime, descriptorsForAllTargetPlaces.size)
|
||||
}
|
||||
@@ -139,10 +182,10 @@ class MethodExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun runInplaceExtract(editor: Editor, range: TextRange, extractor: DuplicatesMethodExtractor, methodNames: List<String>){
|
||||
private suspend fun runInplaceExtract(editor: Editor, extractor: DuplicatesMethodExtractor, methodNames: List<String>){
|
||||
val popupSettings = readAction { createInplaceSettingsPopup(extractor.extractOptions) }
|
||||
val suggestedNames = methodNames.takeIf { it.size > 1 }.orEmpty()
|
||||
val inplaceExtractor = readAction { InplaceMethodExtractor(editor, range, popupSettings, extractor) }
|
||||
val inplaceExtractor = readAction { InplaceMethodExtractor(editor, popupSettings, extractor) }
|
||||
inplaceExtractor.extractAndRunTemplate(suggestedNames)
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -43,6 +43,8 @@ import kotlinx.coroutines.withContext
|
||||
|
||||
class DuplicatesMethodExtractor(val extractOptions: ExtractOptions, val targetClass: PsiClass, val rangeToReplace: RangeMarker) {
|
||||
|
||||
val rangeToReplaceOriginal = rangeToReplace.textRange
|
||||
|
||||
internal fun getElements(): List<PsiElement> {
|
||||
val file = targetClass.containingFile
|
||||
val range = rangeToReplace.textRange
|
||||
|
||||
+11
-73
@@ -6,19 +6,16 @@ import com.intellij.codeInsight.template.impl.TemplateState
|
||||
import com.intellij.ide.util.PropertiesComponent
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.command.writeCommandAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.RangeMarker
|
||||
import com.intellij.openapi.editor.asTextRange
|
||||
import com.intellij.openapi.editor.event.CaretEvent
|
||||
import com.intellij.openapi.editor.event.CaretListener
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil
|
||||
import com.intellij.openapi.editor.impl.EditorImpl
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiMethodCallExpression
|
||||
@@ -45,10 +42,11 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
internal class InplaceMethodExtractor(private val editor: Editor,
|
||||
private val range: TextRange,
|
||||
private val popupProvider: ExtractMethodPopupProvider,
|
||||
private val defaultExtractor: DuplicatesMethodExtractor) {
|
||||
internal class InplaceMethodExtractor(
|
||||
private val editor: Editor,
|
||||
private val popupProvider: ExtractMethodPopupProvider,
|
||||
private val defaultExtractor: DuplicatesMethodExtractor
|
||||
) {
|
||||
|
||||
companion object {
|
||||
private val INPLACE_METHOD_EXTRACTOR = Key<InplaceMethodExtractor>("InplaceMethodExtractor")
|
||||
@@ -62,7 +60,7 @@ internal class InplaceMethodExtractor(private val editor: Editor,
|
||||
}
|
||||
}
|
||||
|
||||
private val extractor: DuplicatesMethodExtractor = createExtractor()
|
||||
internal val extractor: DuplicatesMethodExtractor = createExtractor()
|
||||
|
||||
private val file: PsiFile = defaultExtractor.targetClass.containingFile
|
||||
|
||||
@@ -82,7 +80,7 @@ internal class InplaceMethodExtractor(private val editor: Editor,
|
||||
val analyzer = CodeFragmentAnalyzer(options.elements)
|
||||
options = ExtractMethodPipeline.withForcedStatic(analyzer, options) ?: throw IllegalStateException()
|
||||
}
|
||||
val rangeToReplace = createGreedyRangeMarker(editor.document, range)
|
||||
val rangeToReplace = createGreedyRangeMarker(editor.document, defaultExtractor.rangeToReplaceOriginal)
|
||||
return DuplicatesMethodExtractor(options, defaultExtractor.targetClass, rangeToReplace)
|
||||
}
|
||||
|
||||
@@ -180,75 +178,15 @@ internal class InplaceMethodExtractor(private val editor: Editor,
|
||||
JavaRefactoringSettings.getInstance().EXTRACT_STATIC_METHOD = makeStatic
|
||||
}
|
||||
ExtractMethodService.getInstance(project).scope.launch {
|
||||
restartInplace()
|
||||
MethodExtractor().restartInplace(templateState, defaultExtractor, popupProvider)
|
||||
}
|
||||
}
|
||||
popupProvider.setShowDialogAction { actionEvent -> restartInDialog(actionEvent == null) }
|
||||
popupProvider.setShowDialogAction { actionEvent ->
|
||||
MethodExtractor().restartInDialog(templateState, extractor, actionEvent == null)
|
||||
}
|
||||
addInlaySettingsElement(templateState, popupProvider)?.also { inlay ->
|
||||
Disposer.register(disposable, inlay)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setMethodName(methodName: String) {
|
||||
val callRange = callIdentifierRange ?: return
|
||||
val methodRange = methodIdentifierRange ?: return
|
||||
if (callRange.isValid && callRange.isValid) {
|
||||
editor.document.replaceString(callRange.startOffset, callRange.endOffset, methodName)
|
||||
editor.document.replaceString(methodRange.startOffset, methodRange.endOffset, methodName)
|
||||
PsiDocumentManager.getInstance(project).commitDocument(editor.document)
|
||||
}
|
||||
}
|
||||
|
||||
fun restartInDialog(isLinkUsed: Boolean = false) {
|
||||
val methodRange = callIdentifierRange?.asTextRange
|
||||
val methodName = if (methodRange != null) editor.document.getText(methodRange) else ""
|
||||
InplaceExtractMethodCollector.openExtractDialog.log(project, isLinkUsed)
|
||||
TemplateManagerImpl.getTemplateState(editor)?.gotoEnd(true)
|
||||
val extractOptions = extractor.extractOptions.copy(methodName = methodName)
|
||||
val rangeToReplace = createGreedyRangeMarker(editor.document, range)
|
||||
val extractor = DuplicatesMethodExtractor(extractOptions, extractor.targetClass, rangeToReplace)
|
||||
extractor.extractInDialog()
|
||||
}
|
||||
|
||||
private suspend fun restartInplace() {
|
||||
val startTime = System.currentTimeMillis()
|
||||
val identifierRange = readAction { callIdentifierRange?.asTextRange }
|
||||
val methodName = if (identifierRange != null) readAction { editor.document.getText(identifierRange) } else null
|
||||
|
||||
runWithDumbEditor(editor) {
|
||||
withContext(Dispatchers.EDT) {
|
||||
TemplateManagerImpl.getTemplateState(editor)?.gotoEnd(true)
|
||||
}
|
||||
val inplaceExtractor = readAction { InplaceMethodExtractor(editor, range, popupProvider, defaultExtractor) }
|
||||
inplaceExtractor.extractAndRunTemplate(emptyList())
|
||||
if (methodName != null) {
|
||||
writeCommandAction(project, ExtractMethodHandler.getRefactoringName()) {
|
||||
inplaceExtractor.setMethodName(methodName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val endTime = System.currentTimeMillis()
|
||||
InplaceExtractMethodCollector.previewUpdated.log(endTime - startTime)
|
||||
}
|
||||
|
||||
private suspend fun runWithDumbEditor(editor: Editor, action: suspend () -> Unit) {
|
||||
val editorImpl = editor as? EditorImpl
|
||||
if (editorImpl == null) {
|
||||
action.invoke()
|
||||
return
|
||||
}
|
||||
withContext(Dispatchers.EDT) {
|
||||
editorImpl.startDumb()
|
||||
}
|
||||
try {
|
||||
action.invoke()
|
||||
}
|
||||
finally {
|
||||
withContext(Dispatchers.EDT) {
|
||||
editor.stopDumbLater()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-3
@@ -18,6 +18,7 @@ import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.refactoring.JavaRefactoringSettings
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodHelper
|
||||
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodService
|
||||
import com.intellij.refactoring.extractMethod.newImpl.MethodExtractor
|
||||
import com.intellij.refactoring.extractMethod.newImpl.inplace.DuplicatesMethodExtractor
|
||||
@@ -50,9 +51,7 @@ class ExtractMethodAndDuplicatesInplaceTest: LightJavaCodeInsightTestCase() {
|
||||
fun renameTemplate(templateState: TemplateState?, name: String) {
|
||||
if (templateState == null) return
|
||||
WriteCommandAction.runWriteCommandAction(templateState.project) {
|
||||
val range = templateState.currentVariableRange!!
|
||||
templateState.editor.document.replaceString(range.startOffset, range.endOffset, name)
|
||||
templateState.update()
|
||||
ExtractMethodHelper.renameTemplate(templateState, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user