diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt index 49b35c52f395..6ec502d76afd 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt @@ -3,12 +3,10 @@ package com.intellij.codeInsight.daemon.impl.quickfix import com.intellij.codeInsight.daemon.QuickFixBundle import com.intellij.codeInsight.intention.impl.BaseIntentionAction -import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.* -import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiUtil abstract class AddModuleDirectiveFix(module: PsiJavaModule) : LocalQuickFixAndIntentionActionOnPsiElement(module) { @@ -21,14 +19,6 @@ abstract class AddModuleDirectiveFix(module: PsiJavaModule) : LocalQuickFixAndIn invoke(project, startElement as PsiJavaModule) protected abstract fun invoke(project: Project, module: PsiJavaModule) - - override fun generatePreview(project: Project, editor: Editor, file: PsiFile): IntentionPreviewInfo { - val moduleFile = (startElement.containingFile.copy() as? PsiFile) ?: return IntentionPreviewInfo.EMPTY - val module = (PsiTreeUtil.findSameElementInCopy(startElement, moduleFile) as? PsiJavaModule) ?: return IntentionPreviewInfo.EMPTY - val beforeText = module.text - invoke(project, module) - return IntentionPreviewInfo.CustomDiff(moduleFile.fileType, moduleFile.name, beforeText, module.text) - } } class AddRequiresDirectiveFix(module: PsiJavaModule, private val requiredName: String) : AddModuleDirectiveFix(module) { diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/Java9ReflectionClassVisibilityTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInspection/Java9ReflectionClassVisibilityTest.kt index e12fe500e2b5..0d14b18e9b0d 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/Java9ReflectionClassVisibilityTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/Java9ReflectionClassVisibilityTest.kt @@ -57,7 +57,8 @@ class Java9ReflectionClassVisibilityTest : LightJava9ModulesCodeInsightFixtureTe fun testExportsPackagePreview() { moduleInfo("module MAIN { requires API; }", MAIN) moduleInfo("module API { exports my.api; }", M2) - doTestPreview("Add 'exports my.impl' directive to module-info.java", "module API { exports my.api; exports my.impl; }") + doTestPreview("Add 'exports my.impl' directive to module-info.java", + "module API { exports my.api;\n exports my.impl;\n}") } fun testNotInRequirements() { diff --git a/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java b/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java index 8e277258efa4..503efe391135 100644 --- a/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java +++ b/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java @@ -107,8 +107,10 @@ public interface IntentionAction extends FileModifier { * overriding {@code getFileModifierForPreview} or {@code generatePreview} is desired. * * @param project current project - * @param editor editor. Could be a simplified headless Editor implementation that lacks some features. - * @param file non-physical file to apply + * @param editor editor where a file copy is opened. + * Could be a simplified headless Editor implementation that lacks some features. + * @param file a non-physical file to apply, which is a copy of the file that contains element returned from + * {@link #getElementToMakeWritable(PsiFile)}, or copy of the current file if that method returns null * @return an object that describes the action preview to display */ default @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/preview/IntentionPreviewComputable.kt b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/preview/IntentionPreviewComputable.kt index 556c916e9e85..d6050d7c88b2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/preview/IntentionPreviewComputable.kt +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/preview/IntentionPreviewComputable.kt @@ -107,11 +107,14 @@ internal class IntentionPreviewComputable(private val project: Project, IntentionPreviewInfo.DIFF, IntentionPreviewInfo.DIFF_NO_TRIM -> { val document = psiFileCopy!!.viewProvider.document + val anotherFile = psiFileCopy.originalFile != origFile val policy = if (result == IntentionPreviewInfo.DIFF) ComparisonPolicy.TRIM_WHITESPACES else ComparisonPolicy.DEFAULT IntentionPreviewDiffResult( psiFile = psiFileCopy, - origFile = origFile, + origFile = psiFileCopy.originalFile, policy = policy, + fileName = if (anotherFile) psiFileCopy.name else null, + normalDiff = !anotherFile, lineFragments = comparisonManager.compareLines(origFile.text, document.text, policy, DumbProgressIndicator.INSTANCE)) } IntentionPreviewInfo.EMPTY, IntentionPreviewInfo.FALLBACK_DIFF -> null @@ -135,21 +138,22 @@ internal class IntentionPreviewComputable(private val project: Project, private fun invokePreview(origFile: PsiFile, selection: TextRange, caretOffset: Int): Pair { var info: IntentionPreviewInfo = IntentionPreviewInfo.EMPTY - val psiFileCopy = IntentionPreviewUtils.obtainCopyForPreview(origFile) + val fileToCopy = action.getElementToMakeWritable(origFile) ?. containingFile ?: origFile + val psiFileCopy = IntentionPreviewUtils.obtainCopyForPreview(fileToCopy) val editorCopy = IntentionPreviewEditor(psiFileCopy, originalEditor.settings) - editorCopy.caretModel.moveToOffset(caretOffset) - editorCopy.selectionModel.setSelection(selection.startOffset, selection.endOffset) + if (fileToCopy == origFile) { + editorCopy.caretModel.moveToOffset(caretOffset) + editorCopy.selectionModel.setSelection(selection.startOffset, selection.endOffset) + } originalEditor.document.setReadOnly(true) ProgressManager.checkCanceled() IntentionPreviewUtils.previewSession(editorCopy) { PostprocessReformattingAspect.getInstance(project) .postponeFormattingInside { info = action.generatePreview(project, editorCopy, psiFileCopy) } } - if (info == IntentionPreviewInfo.FALLBACK_DIFF) { + if (info == IntentionPreviewInfo.FALLBACK_DIFF && fileToCopy == origFile) { if (!action.startInWriteAction()) return info to null if (action.getElementToMakeWritable(originalFile)?.containingFile !== originalFile) return info to null - // Use fallback algorithm only if invokeForPreview is not explicitly overridden - // in this case, the absence of diff could be intended, thus should not be logged as error val action = findCopyIntention(project, editorCopy, psiFileCopy, action) ?: return info to null val unwrapped = IntentionActionDelegate.unwrap(action) val cls = (if (unwrapped is QuickFixWrapper) unwrapped.fix else unwrapped)::class.java