mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
EA-54811 - avoid InjectedCodeFoldingPass seeing outdated PSI for injected fragments
This commit is contained in:
@@ -15,11 +15,8 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.codeInsight.daemon.impl.CodeFoldingPassFactory;
|
||||
import com.intellij.mock.MockProgressIndicator;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.EditorTestUtil;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
|
||||
@@ -43,14 +40,7 @@ public class FoldingExceptionTest extends LightCodeInsightTestCase {
|
||||
}
|
||||
|
||||
private static void runFoldingPass() {
|
||||
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(getProject());
|
||||
psiDocumentManager.commitAllDocuments();
|
||||
PsiFile psiFile = psiDocumentManager.getPsiFile(myEditor.getDocument());
|
||||
assertNotNull(psiFile);
|
||||
|
||||
CodeFoldingPassFactory factory = getProject().getComponent(CodeFoldingPassFactory.class);
|
||||
TextEditorHighlightingPass highlightingPass = factory.createHighlightingPass(psiFile, myEditor);
|
||||
highlightingPass.collectInformation(new MockProgressIndicator());
|
||||
highlightingPass.doApplyInformationToEditor();
|
||||
PsiDocumentManager.getInstance(ourProject).commitAllDocuments();
|
||||
EditorTestUtil.runTextEditorHighlightingPass(myEditor, CodeFoldingPassFactory.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,17 +159,24 @@ public class FoldingUpdate {
|
||||
final List<EditorWindow> injectedEditors = new ArrayList<EditorWindow>();
|
||||
final List<PsiFile> injectedFiles = new ArrayList<PsiFile>();
|
||||
final List<FoldingMap> maps = new ArrayList<FoldingMap>();
|
||||
for (DocumentWindow injectedDocument : injectedDocuments) {
|
||||
PsiFile injectedFile = PsiDocumentManager.getInstance(project).getPsiFile(injectedDocument);
|
||||
if (injectedFile == null || !injectedFile.isValid() || !injectedDocument.isValid()) continue;
|
||||
Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile);
|
||||
if (!(injectedEditor instanceof EditorWindow)) continue;
|
||||
for (final DocumentWindow injectedDocument : injectedDocuments) {
|
||||
if (!injectedDocument.isValid()) {
|
||||
continue;
|
||||
}
|
||||
InjectedLanguageUtil.enumerate(injectedDocument, file, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull PsiFile injectedFile, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
if (!injectedFile.isValid()) return;
|
||||
Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile);
|
||||
if (!(injectedEditor instanceof EditorWindow)) return;
|
||||
|
||||
injectedEditors.add((EditorWindow)injectedEditor);
|
||||
injectedFiles.add(injectedFile);
|
||||
final FoldingMap map = new FoldingMap();
|
||||
maps.add(map);
|
||||
getFoldingsFor(injectedFile, injectedDocument, map, false);
|
||||
injectedEditors.add((EditorWindow)injectedEditor);
|
||||
injectedFiles.add(injectedFile);
|
||||
final FoldingMap map = new FoldingMap();
|
||||
maps.add(map);
|
||||
getFoldingsFor(injectedFile, injectedDocument, map, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return new Runnable() {
|
||||
|
||||
+1
-11
@@ -43,7 +43,6 @@ import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
@@ -141,18 +140,9 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme
|
||||
if (indicator != null && indicator.isCanceled()) return false;
|
||||
if (documentManager.isUncommited(hostDocument) || !hostPsiFile.isValid()) return false; // will be committed later
|
||||
|
||||
Segment[] ranges = documentWindow.getHostRanges();
|
||||
Segment rangeMarker = ranges.length > 0 ? ranges[0] : null;
|
||||
PsiElement element = rangeMarker == null ? null : hostPsiFile.findElementAt(rangeMarker.getStartOffset());
|
||||
if (element == null) {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
injected.remove(documentWindow);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
final DocumentWindow[] stillInjectedDocument = {null};
|
||||
// it is here where the reparse happens and old file contents replaced
|
||||
InjectedLanguageUtil.enumerate(element, hostPsiFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
InjectedLanguageUtil.enumerate(documentWindow, hostPsiFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
stillInjectedDocument[0] = (DocumentWindow)injectedPsi.getViewProvider().getDocument();
|
||||
|
||||
+11
@@ -92,6 +92,17 @@ public class InjectedLanguageUtil {
|
||||
return ((DocumentWindowImpl)myFileViewProvider.getDocument()).getShreds();
|
||||
}
|
||||
|
||||
public static void enumerate(@NotNull DocumentWindow documentWindow,
|
||||
@NotNull PsiFile hostPsiFile,
|
||||
@NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
|
||||
Segment[] ranges = documentWindow.getHostRanges();
|
||||
Segment rangeMarker = ranges.length > 0 ? ranges[0] : null;
|
||||
PsiElement element = rangeMarker == null ? null : hostPsiFile.findElementAt(rangeMarker.getStartOffset());
|
||||
if (element != null) {
|
||||
enumerate(element, hostPsiFile, true, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean enumerate(@NotNull PsiElement host, @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
|
||||
PsiFile containingFile = host.getContainingFile();
|
||||
return enumerate(host, containingFile, true, visitor);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,10 +15,8 @@
|
||||
*/
|
||||
package com.intellij.psi.formatter;
|
||||
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.codeInsight.daemon.impl.CodeFoldingPassFactory;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.mock.MockProgressIndicator;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
@@ -42,6 +40,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.testFramework.EditorTestUtil;
|
||||
import com.intellij.testFramework.LightPlatformTestCase;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
@@ -199,7 +198,7 @@ public abstract class FormatterTestCase extends LightPlatformTestCase {
|
||||
assertEquals(file.getText(), document.getText());
|
||||
|
||||
if (false && doCheckDocumentUpdate()) {
|
||||
makeFolding(file, editor);
|
||||
EditorTestUtil.runTextEditorHighlightingPass(editor, CodeFoldingPassFactory.class);
|
||||
}
|
||||
try {
|
||||
if (doReformatRangeTest) {
|
||||
@@ -225,13 +224,6 @@ public abstract class FormatterTestCase extends LightPlatformTestCase {
|
||||
assertEquals(textAfter, file.getText());
|
||||
}
|
||||
|
||||
protected static void makeFolding(final PsiFile file, final EditorImpl editor) {
|
||||
final CodeFoldingPassFactory factory = getProject().getComponent(CodeFoldingPassFactory.class);
|
||||
final TextEditorHighlightingPass highlightingPass = factory.createHighlightingPass(file, editor);
|
||||
highlightingPass.collectInformation(new MockProgressIndicator());
|
||||
highlightingPass.doApplyInformationToEditor();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UNUSED_SYMBOL"})
|
||||
private void checkPsi(final PsiFile file, String textAfter) {
|
||||
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
*/
|
||||
package com.intellij.testFramework;
|
||||
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.mock.MockProgressIndicator;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
@@ -32,10 +35,13 @@ import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
|
||||
import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType;
|
||||
import com.intellij.openapi.editor.impl.softwrap.SoftWrapPainter;
|
||||
import com.intellij.openapi.editor.impl.softwrap.mapping.SoftWrapApplianceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -432,6 +438,20 @@ public class EditorTestUtil {
|
||||
return ref.get();
|
||||
}
|
||||
|
||||
public static <T extends TextEditorHighlightingPassFactory> void runTextEditorHighlightingPass(@NotNull Editor editor, @NotNull Class<T> passFactory) {
|
||||
Project project = editor.getProject();
|
||||
assertNotNull(project);
|
||||
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project);
|
||||
PsiFile psiFile = psiDocumentManager.getPsiFile(editor.getDocument());
|
||||
assertNotNull(psiFile);
|
||||
|
||||
T factory = project.getComponent(passFactory);
|
||||
TextEditorHighlightingPass pass = factory.createHighlightingPass(psiFile, editor);
|
||||
assertNotNull(pass);
|
||||
pass.collectInformation(new MockProgressIndicator());
|
||||
pass.applyInformationToEditor();
|
||||
}
|
||||
|
||||
public static class CaretAndSelectionState {
|
||||
public final List<CaretInfo> carets = new ArrayList<CaretInfo>();
|
||||
@Nullable
|
||||
|
||||
Reference in New Issue
Block a user