mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
smartPointer.get(Psi)Range should be not-null for valid pointers; fix related data race (EA-74922 - assert: TextRange.<init>)
This commit is contained in:
+19
@@ -877,4 +877,23 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
|
||||
private <T extends PsiElement> SmartPointerEx<T> createPointer(T element) {
|
||||
return (SmartPointerEx<T>)getPointerManager().createSmartPsiElementPointer(element);
|
||||
}
|
||||
|
||||
public void testAnchorInfoHasRange() throws Exception {
|
||||
PsiJavaFile file = (PsiJavaFile)createFile("a.java", "class C1{}");
|
||||
assertNotNull(((PsiFileImpl) file).getStubTree());
|
||||
PsiClass psiClass = file.getClasses()[0];
|
||||
|
||||
Segment range = createPointer(psiClass).getRange();
|
||||
assertNotNull(range);
|
||||
assertEquals(psiClass.getNameIdentifier().getTextRange(), TextRange.create(range));
|
||||
|
||||
file = (PsiJavaFile)createFile("b.java", "class C2{}");
|
||||
assertNotNull(((PsiFileImpl) file).getStubTree());
|
||||
psiClass = file.getClasses()[0];
|
||||
|
||||
range = createPointer(psiClass).getPsiRange();
|
||||
assertNotNull(range);
|
||||
assertEquals(psiClass.getNameIdentifier().getTextRange(), TextRange.create(range));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.lang.LanguageUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiAnchor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -102,16 +102,17 @@ class AnchorElementInfo extends SelfElementInfo {
|
||||
@Override
|
||||
public boolean pointsToTheSameElementAs(@NotNull final SmartPointerElementInfo other) {
|
||||
if (other instanceof AnchorElementInfo) {
|
||||
AnchorElementInfo otherAnchor = (AnchorElementInfo)other;
|
||||
if ((getStubId() == -1) != (otherAnchor.getStubId() == -1)) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return Comparing.equal(restoreElement(), other.restoreElement());
|
||||
}
|
||||
});
|
||||
if (!getVirtualFile().equals(other.getVirtualFile())) return false;
|
||||
|
||||
long packed1 = myStubElementTypeAndId;
|
||||
long packed2 = ((AnchorElementInfo)other).myStubElementTypeAndId;
|
||||
|
||||
if (packed1 != -1 && packed2 != -1) {
|
||||
return packed1 == packed2;
|
||||
}
|
||||
if (packed1 != -1 || packed2 != -1) {
|
||||
return areRestoredElementsEqual(other);
|
||||
}
|
||||
if (myStubElementTypeAndId != otherAnchor.myStubElementTypeAndId) return false;
|
||||
}
|
||||
return super.pointsToTheSameElementAs(other);
|
||||
}
|
||||
@@ -126,9 +127,7 @@ class AnchorElementInfo extends SelfElementInfo {
|
||||
|
||||
private void switchToTree() {
|
||||
PsiElement element = restoreElement();
|
||||
Document document = getDocumentToSynchronize();
|
||||
if (element != null && document != null) {
|
||||
// switch to tree
|
||||
if (element != null) {
|
||||
PsiElement anchor = AnchorElementInfoFactory.getAnchor(element);
|
||||
if (anchor == null) anchor = element;
|
||||
myType = AnchorTypeInfo.obtainInfo(anchor, myType.getFileLanguage());
|
||||
@@ -146,4 +145,12 @@ class AnchorElementInfo extends SelfElementInfo {
|
||||
return super.getRange();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ProperTextRange getPsiRange() {
|
||||
if (getStubId() != -1) {
|
||||
switchToTree();
|
||||
}
|
||||
return super.getPsiRange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,16 +232,19 @@ public class SelfElementInfo extends SmartPointerElementInfo {
|
||||
public boolean pointsToTheSameElementAs(@NotNull final SmartPointerElementInfo other) {
|
||||
if (other instanceof SelfElementInfo) {
|
||||
SelfElementInfo otherInfo = (SelfElementInfo)other;
|
||||
if (!getVirtualFile().equals(other.getVirtualFile()) || myType != otherInfo.myType) return false;
|
||||
|
||||
Segment range1 = getPsiRange();
|
||||
Segment range2 = otherInfo.getPsiRange();
|
||||
return Comparing.equal(getVirtualFile(), otherInfo.getVirtualFile())
|
||||
&& myType == otherInfo.myType
|
||||
&& range1 != null
|
||||
&& range2 != null
|
||||
return range1 != null && range2 != null
|
||||
&& range1.getStartOffset() == range2.getStartOffset()
|
||||
&& range1.getEndOffset() == range2.getEndOffset()
|
||||
;
|
||||
}
|
||||
return areRestoredElementsEqual(other);
|
||||
}
|
||||
|
||||
protected boolean areRestoredElementsEqual(@NotNull final SmartPointerElementInfo other) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
|
||||
Reference in New Issue
Block a user