mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
assert that just created smart pointers can always be restored correctly + handle corner cases of empty-ranged PSI
This commit is contained in:
+1
-1
@@ -207,7 +207,7 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
|
||||
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
PlatformTestUtil.tryGcSoftlyReachableObjects();
|
||||
assertNull(pointer.getElement());
|
||||
assertEquals(myFile.getFirstChild(), pointer.getElement());
|
||||
}
|
||||
|
||||
public void testChangeInPsi() {
|
||||
|
||||
@@ -132,6 +132,9 @@ public class SelfElementInfo extends SmartPointerElementInfo {
|
||||
@NotNull Class type,
|
||||
@NotNull Language language) {
|
||||
PsiElement anchor = file.getViewProvider().findElementAt(syncStartOffset, language);
|
||||
if (anchor == null && syncStartOffset == file.getTextLength()) {
|
||||
anchor = PsiTreeUtil.getDeepestLast(file.getViewProvider().getPsi(language).getLastChild());
|
||||
}
|
||||
if (anchor == null) return null;
|
||||
|
||||
PsiElement result = findParent(syncStartOffset, syncEndOffset, type, anchor);
|
||||
|
||||
+22
@@ -19,6 +19,7 @@ package com.intellij.psi.impl.smartPointers;
|
||||
import com.intellij.lang.LanguageUtil;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -30,6 +31,8 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.FreeThreadedFileViewProvider;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.impl.source.tree.ForeignLeafPsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -38,6 +41,8 @@ import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx<E> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.smartPointers.SmartPsiElementPointerImpl");
|
||||
|
||||
private Reference<E> myElement;
|
||||
private final SmartPointerElementInfo myElementInfo;
|
||||
private final Class<? extends PsiElement> myElementClass;
|
||||
@@ -138,6 +143,18 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
|
||||
private static <E extends PsiElement> SmartPointerElementInfo createElementInfo(@NotNull Project project,
|
||||
@NotNull E element,
|
||||
PsiFile containingFile) {
|
||||
SmartPointerElementInfo elementInfo = doCreateElementInfo(project, element, containingFile);
|
||||
if (ApplicationManager.getApplication().isUnitTestMode() && !element.equals(elementInfo.restoreElement())) {
|
||||
// likely cause: PSI having isPhysical==true, but which can't be restored by containing file and range. To fix, make isPhysical return false
|
||||
LOG.error("Cannot restore " + element + " of " + element.getClass() + " from " + elementInfo);
|
||||
}
|
||||
return elementInfo;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static <E extends PsiElement> SmartPointerElementInfo doCreateElementInfo(@NotNull Project project,
|
||||
@NotNull E element,
|
||||
PsiFile containingFile) {
|
||||
if (element instanceof PsiDirectory) {
|
||||
return new DirElementInfo((PsiDirectory)element);
|
||||
}
|
||||
@@ -177,6 +194,11 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
|
||||
if (elementRange == null) {
|
||||
return new HardElementInfo(project, element);
|
||||
}
|
||||
if (elementRange.isEmpty() && PsiTreeUtil.findChildOfType(element, ForeignLeafPsiElement.class) != null) {
|
||||
// PSI built on C-style macro expansions. It has empty ranges, no text, but complicated structure. It can't be reliably
|
||||
// restored by just one offset in a file, so hold it on a hard reference
|
||||
return new HardElementInfo(project, element);
|
||||
}
|
||||
ProperTextRange proper = ProperTextRange.create(elementRange);
|
||||
|
||||
return new SelfElementInfo(project, proper, element.getClass(), containingFile, LanguageUtil.getRootLanguage(element), false);
|
||||
|
||||
Reference in New Issue
Block a user