mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-175229 PSI changes should be reflected in the corresponding document even if PSI is non-physical
This commit is contained in:
@@ -345,7 +345,7 @@ public class PomModelImpl extends UserDataHolderBase implements PomModel {
|
||||
}
|
||||
|
||||
boolean physical = changeScope.isPhysical();
|
||||
if (physical && synchronizer.toProcessPsiEvent()) {
|
||||
if (synchronizer.toProcessPsiEvent()) {
|
||||
// fail-fast to prevent any psi modifications that would cause psi/document text mismatch
|
||||
// PsiToDocumentSynchronizer assertions happen inside event processing and are logged by PsiManagerImpl.fireEvent instead of being rethrown
|
||||
// so it's important to throw something outside event processing
|
||||
@@ -353,7 +353,7 @@ public class PomModelImpl extends UserDataHolderBase implements PomModel {
|
||||
throw new IllegalStateException("Attempt to modify PSI for non-committed Document!");
|
||||
}
|
||||
CommandProcessor commandProcessor = CommandProcessor.getInstance();
|
||||
if (!commandProcessor.isUndoTransparentActionInProgress() && commandProcessor.getCurrentCommand() == null) {
|
||||
if (physical && !commandProcessor.isUndoTransparentActionInProgress() && commandProcessor.getCurrentCommand() == null) {
|
||||
throw new IncorrectOperationException("Must not change PSI outside command or undo-transparent action. See com.intellij.openapi.command.WriteCommandAction or com.intellij.openapi.command.CommandProcessor");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter {
|
||||
return file.getUserData(PSI_DOCUMENT_ATOMIC_ACTION) == Boolean.TRUE;
|
||||
}
|
||||
|
||||
static void performAtomically(@NotNull PsiFile file, @NotNull Runnable runnable) {
|
||||
public static void performAtomically(@NotNull PsiFile file, @NotNull Runnable runnable) {
|
||||
PsiUtilCore.ensureValid(file);
|
||||
assert !isInsideAtomicChange(file);
|
||||
file.putUserData(PSI_DOCUMENT_ATOMIC_ACTION, Boolean.TRUE);
|
||||
|
||||
@@ -370,7 +370,7 @@ public class DaemonListeners implements Disposable {
|
||||
if (project != null && project != myProject) return false;
|
||||
// cached is essential here since we do not want to create PSI file in alien project
|
||||
PsiFile psiFile = myPsiDocumentManager.getCachedPsiFile(document);
|
||||
return psiFile != null && psiFile.getOriginalFile() == psiFile;
|
||||
return psiFile != null && psiFile.isPhysical() && psiFile.getOriginalFile() == psiFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
|
||||
package com.intellij.pom.wrappers;
|
||||
|
||||
import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.PomModel;
|
||||
import com.intellij.pom.PomModelAspect;
|
||||
import com.intellij.pom.event.PomModelEvent;
|
||||
@@ -27,11 +31,12 @@ import com.intellij.pom.tree.events.TreeChange;
|
||||
import com.intellij.pom.tree.events.TreeChangeEvent;
|
||||
import com.intellij.pom.tree.events.impl.ChangeInfoImpl;
|
||||
import com.intellij.pom.tree.events.impl.TreeChangeImpl;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.*;
|
||||
import com.intellij.psi.impl.source.DummyHolder;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -52,11 +57,12 @@ public class PsiEventWrapperAspect implements PomModelAspect{
|
||||
|
||||
private static void sendAfterEvents(TreeChangeEvent changeSet) {
|
||||
ASTNode rootElement = changeSet.getRootElement();
|
||||
final PsiFile file = (PsiFile)SourceTreeToPsiMap.treeElementToPsi(rootElement);
|
||||
final PsiManagerImpl manager = (PsiManagerImpl)file.getManager();
|
||||
PsiFile file = (PsiFile)rootElement.getPsi();
|
||||
PsiManagerImpl manager = (PsiManagerImpl)file.getManager();
|
||||
if(manager == null) return;
|
||||
|
||||
if (!file.isPhysical()) {
|
||||
promoteNonPhysicalChangesToDocument(rootElement, file);
|
||||
manager.afterChange(false);
|
||||
return;
|
||||
}
|
||||
@@ -120,6 +126,20 @@ public class PsiEventWrapperAspect implements PomModelAspect{
|
||||
}
|
||||
}
|
||||
|
||||
private static void promoteNonPhysicalChangesToDocument(ASTNode rootElement, PsiFile file) {
|
||||
if (file instanceof DummyHolder) return;
|
||||
if (((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(file.getProject())).isCommitInProgress()) return;
|
||||
|
||||
VirtualFile vFile = file.getViewProvider().getVirtualFile();
|
||||
if (vFile instanceof LightVirtualFile && !(vFile instanceof VirtualFileWindow)) {
|
||||
Document document = FileDocumentManager.getInstance().getCachedDocument(vFile);
|
||||
if (document != null) {
|
||||
CharSequence text = rootElement.getChars();
|
||||
PsiToDocumentSynchronizer.performAtomically(file, () -> document.replaceString(0, document.getTextLength(), text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkPsiForChildren(final ASTNode[] affectedChildren) {
|
||||
for (final ASTNode astNode : affectedChildren) {
|
||||
//if (TreeUtil.isCollapsedChameleon(astNode)) return false;
|
||||
|
||||
+5
-2
@@ -28,6 +28,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.SingleRootFileViewProvider;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class DocumentUndoProvider implements Disposable {
|
||||
@@ -96,8 +97,10 @@ public class DocumentUndoProvider implements Disposable {
|
||||
private boolean shouldRecordActions(final Document document) {
|
||||
if (document.getUserData(UndoConstants.DONT_RECORD_UNDO) == Boolean.TRUE) return false;
|
||||
|
||||
final VirtualFile vFile = FileDocumentManager.getInstance().getFile(document);
|
||||
return vFile == null || vFile.getUserData(UndoConstants.DONT_RECORD_UNDO) != Boolean.TRUE;
|
||||
VirtualFile vFile = FileDocumentManager.getInstance().getFile(document);
|
||||
if (vFile == null) return true;
|
||||
return vFile.getUserData(SingleRootFileViewProvider.FREE_THREADED) != Boolean.TRUE &&
|
||||
vFile.getUserData(UndoConstants.DONT_RECORD_UNDO) != Boolean.TRUE;
|
||||
}
|
||||
|
||||
private void registerUndoableAction(DocumentEvent e) {
|
||||
|
||||
Reference in New Issue
Block a user