diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java index e8daf7b482b8..b54a18f42467 100644 --- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java +++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java @@ -97,7 +97,7 @@ class AnchorElementInfo extends SelfElementInfo { } @Override - public void fastenBelt(int offset, RangeMarker cachedRangeMarker) { + public void fastenBelt(int offset, RangeMarker[] cachedRangeMarker) { if (stubId != -1) { PsiElement element = restoreElement(); if (element != null) { diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/ImplicitVariableElementInfoFactory.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/ImplicitVariableElementInfoFactory.java index 72f54c44be42..a75bca964594 100644 --- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/ImplicitVariableElementInfoFactory.java +++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/ImplicitVariableElementInfoFactory.java @@ -65,7 +65,7 @@ public class ImplicitVariableElementInfoFactory implements SmartPointerElementIn } @Override - public void fastenBelt(int offset, RangeMarker cachedRangeMarker) { + public void fastenBelt(int offset, RangeMarker[] cachedRangeMarker) { } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/ClsElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/ClsElementInfo.java index 8beb1f7f0389..91d15d3b2941 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/ClsElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/ClsElementInfo.java @@ -42,7 +42,7 @@ public class ClsElementInfo implements SmartPointerElementInfo { // before change @Override - public void fastenBelt(int offset, RangeMarker cachedRangeMarker) { + public void fastenBelt(int offset, RangeMarker[] cachedRangeMarker) { } // after change diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/FileElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/FileElementInfo.java index f8d65182518c..a4356e3a9b7b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/FileElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/FileElementInfo.java @@ -58,7 +58,7 @@ class FileElementInfo implements SmartPointerElementInfo { } @Override - public void fastenBelt(int offset, RangeMarker cachedRangeMarker) { + public void fastenBelt(int offset, RangeMarker[] cachedRangeMarker) { } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/HardElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/HardElementInfo.java index 42bbf66f8055..f769351741e9 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/HardElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/HardElementInfo.java @@ -47,7 +47,7 @@ class HardElementInfo implements SmartPointerElementInfo { } @Override - public void fastenBelt(int offset, RangeMarker cachedRangeMarker) { + public void fastenBelt(int offset, RangeMarker[] cachedRangeMarker) { } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java index 423d187dff4f..c3fa384ef0d2 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java @@ -88,7 +88,7 @@ public class SelfElementInfo implements SmartPointerElementInfo { setRange(anchor); } - protected void setRange(TextRange range) { + protected void setRange(@NotNull Segment range) { mySyncStartOffset = range.getStartOffset(); mySyncEndOffset = range.getEndOffset(); } @@ -104,7 +104,7 @@ public class SelfElementInfo implements SmartPointerElementInfo { // before change @Override - public void fastenBelt(int offset, @Nullable RangeMarker cachedRangeMarker) { + public void fastenBelt(int offset, @Nullable RangeMarker[] cachedRangeMarkers) { if (!mySyncMarkerIsValid) return; RangeMarker marker = getMarker(); int actualEndOffset = marker == null || !marker.isValid() ? getSyncEndOffset() : marker.getEndOffset(); @@ -120,11 +120,15 @@ public class SelfElementInfo implements SmartPointerElementInfo { int start = Math.min(getSyncStartOffset(), document.getTextLength()); int end = Math.min(Math.max(getSyncEndOffset(), start), document.getTextLength()); // use supplied cached markers if available - if (cachedRangeMarker != null && - cachedRangeMarker.isValid() && - cachedRangeMarker.getStartOffset() == start && - cachedRangeMarker.getEndOffset() == end) { - marker = cachedRangeMarker; + if (cachedRangeMarkers != null) { + for (RangeMarker cachedRangeMarker : cachedRangeMarkers) { + if (cachedRangeMarker.isValid() && + cachedRangeMarker.getStartOffset() == start && + cachedRangeMarker.getEndOffset() == end) { + marker = cachedRangeMarker; + break; + } + } } else { marker = document.createRangeMarker(start, end, true); @@ -147,8 +151,7 @@ public class SelfElementInfo implements SmartPointerElementInfo { RangeMarker marker = getMarker(); if (marker != null) { if (marker.isValid()) { - mySyncStartOffset = marker.getStartOffset(); - mySyncEndOffset = marker.getEndOffset(); + setRange(marker); assert mySyncEndOffset <= marker.getDocument().getTextLength() : "mySyncEndOffset: "+mySyncEndOffset+"; docLength: "+marker.getDocument().getTextLength()+"; marker: "+marker +"; "+marker.getClass(); } else { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerElementInfo.java index 6a986a4a24a2..4a8b5ecb4cfb 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerElementInfo.java @@ -30,7 +30,7 @@ interface SmartPointerElementInfo { Document getDocumentToSynchronize(); void documentAndPsiInSync(); - void fastenBelt(int offset, RangeMarker cachedRangeMarker); + void fastenBelt(int offset, RangeMarker[] cachedRangeMarkers); void unfastenBelt(int offset); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerEx.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerEx.java index 455faa596ecf..afed7d94ef9e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerEx.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerEx.java @@ -21,7 +21,7 @@ import com.intellij.psi.SmartPsiElementPointer; import org.jetbrains.annotations.Nullable; public interface SmartPointerEx extends SmartPsiElementPointer { - void fastenBelt(int offset, @Nullable RangeMarker cachedRangeMarker); + void fastenBelt(int offset, @Nullable RangeMarker[] cachedRangeMarkers); void documentAndPsiInSync(); void unfastenBelt(int offset); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java index fb8722d0156b..9aab4da80572 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java @@ -18,7 +18,6 @@ package com.intellij.psi.impl.smartPointers; import com.intellij.injected.editor.DocumentWindow; import com.intellij.lang.Language; -import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; @@ -29,11 +28,13 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.ProperTextRange; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.injected.InjectedFileViewProvider; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.reference.SoftReference; import com.intellij.util.containers.UnsafeWeakList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import java.lang.ref.Reference; import java.util.List; @@ -51,7 +52,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager { myProject = project; } - public void fastenBelts(@NotNull PsiFile file, int offset, @Nullable RangeMarker cachedRangeMarker) { + public void fastenBelts(@NotNull PsiFile file, int offset, @Nullable RangeMarker[] cachedRangeMarkers) { synchronized (file) { if (areBeltsFastened(file)) return; @@ -68,30 +69,23 @@ public class SmartPointerManagerImpl extends SmartPointerManager { for (int i = 0; i < pointers.size(); i++) { SmartPointerEx pointer = pointers.get(i); if (pointer != null) { - pointer.fastenBelt(offset, cachedRangeMarker); + pointer.fastenBelt(offset, cachedRangeMarkers); } } for (DocumentWindow injectedDoc : InjectedLanguageUtil.getCachedInjectedDocuments(file)) { PsiFile injectedFile = psiDocumentManager.getPsiFile(injectedDoc); if (injectedFile == null) continue; - RangeMarker cachedMarker = getCachedRangeMarkerToInjectedFragment(injectedFile); - fastenBelts(injectedFile, 0, cachedMarker); + RangeMarker[] cachedMarkers = getCachedRangeMarkerToInjectedFragment(injectedFile); + fastenBelts(injectedFile, 0, cachedMarkers); } } } - private static RangeMarker getCachedRangeMarkerToInjectedFragment(@NotNull PsiFile injectedFile) { - PsiElement hostContext = InjectedLanguageManager.getInstance(injectedFile.getProject()).getInjectionHost(injectedFile); - RangeMarker cachedMarker = null; - if (hostContext != null) { - SmartPsiElementPointer cachedPointer = getCachedPointer(hostContext); - SmartPointerElementInfo info = cachedPointer == null ? null : ((SmartPsiElementPointerImpl)cachedPointer).getElementInfo(); - if (info instanceof SelfElementInfo) { - cachedMarker = ((SelfElementInfo)info).getMarker(); - } - } - return cachedMarker; + @NotNull + private static RangeMarker[] getCachedRangeMarkerToInjectedFragment(@NotNull PsiFile injectedFile) { + InjectedFileViewProvider provider = (InjectedFileViewProvider)injectedFile.getViewProvider(); + return provider.getCachedMarkers(); } public void unfastenBelts(@NotNull PsiFile file, int offset) { @@ -221,6 +215,12 @@ public class SmartPointerManagerImpl extends SmartPointerManager { return containingFile.getUserData(SMART_POINTERS_IN_PSI_FILE_KEY); } + @TestOnly + public int getPointersNumber(@NotNull PsiFile containingFile) { + List pointers = getPointers(containingFile); + return pointers == null ? 0 : pointers.size(); + } + private static boolean areBeltsFastened(@NotNull PsiFile file) { return file.getUserData(BELTS_ARE_FASTEN_KEY) == Boolean.TRUE; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java index 325d4045175c..5114e62bfe4f 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java @@ -201,8 +201,8 @@ class SmartPsiElementPointerImpl implements SmartPointerEx } @Override - public void fastenBelt(int offset, @Nullable RangeMarker cachedRangeMarker) { - myElementInfo.fastenBelt(offset, cachedRangeMarker); + public void fastenBelt(int offset, @Nullable RangeMarker[] cachedRangeMarkers) { + myElementInfo.fastenBelt(offset, cachedRangeMarkers); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java index 4cd558854598..7e10c9e4ef8a 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java @@ -21,6 +21,7 @@ import com.intellij.injected.editor.DocumentWindowImpl; import com.intellij.injected.editor.VirtualFileWindow; import com.intellij.lang.Language; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; @@ -30,6 +31,8 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.FreeThreadedFileViewProvider; +import com.intellij.util.SmartList; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -189,6 +192,7 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme } } + @NonNls @Override public String toString() { return "Injected file '"+getVirtualFile().getName()+"' " + (isValid() ? "" : " invalid") + (isPhysical() ? "" : " nonphysical"); @@ -197,4 +201,16 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme public void setPatchingLeaves(boolean patchingLeaves) { myPatchingLeaves = patchingLeaves; } + + @NotNull + public RangeMarker[] getCachedMarkers() { + List markers = new SmartList(); + for (PsiLanguageInjectionHost.Shred shred : myDocumentWindow.getShreds()) { + RangeMarker marker = (RangeMarker)shred.getHostRangeMarker(); + if (marker != null) { + markers.add(marker); + } + } + return markers.toArray(new RangeMarker[markers.size()]); + } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java index 873d8353ace9..ed22ad146497 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java @@ -61,7 +61,7 @@ class ShredImpl implements PsiLanguageInjectionHost.Shred { @Nullable("returns null when the host document marker is invalid") public Segment getHostRangeMarker() { RangeMarker marker = relevantRangeInHost; - return marker == null || !marker.isValid() ? null : marker; + return marker.isValid() ? marker : null; } @Override