mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
removing of smart pointers fixed
This commit is contained in:
+43
-1
@@ -13,10 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi;
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.CodeInsightTestCase;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
@@ -26,6 +27,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import com.intellij.psi.impl.source.tree.FileElement;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -38,6 +40,7 @@ import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.util.FileContentUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
@@ -374,4 +377,43 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
|
||||
|
||||
assertFalse(SmartPointerManager.getInstance(myProject).pointToTheSameElement(pointer1, pointer2));
|
||||
}
|
||||
|
||||
public void testPointersRefCount() throws Exception {
|
||||
PsiFile file = configureByText(JavaFileType.INSTANCE, "class X{}");
|
||||
PsiClass aClass = ((PsiClassOwner)file).getClasses()[0];
|
||||
SmartPointerManagerImpl smartPointerManager = (SmartPointerManagerImpl)SmartPointerManager.getInstance(myProject);
|
||||
SmartPsiElementPointer pointer1 = smartPointerManager.createSmartPsiElementPointer(aClass);
|
||||
SmartPsiElementPointer pointer2 = smartPointerManager.createSmartPsiElementPointer(aClass);
|
||||
assertSame(pointer1, pointer2);
|
||||
|
||||
assertNotNull(pointer1.getRange());
|
||||
|
||||
boolean removed2 = smartPointerManager.removePointer(pointer2);
|
||||
assertFalse(removed2);
|
||||
assertNotNull(pointer1.getRange());
|
||||
|
||||
boolean removed1 = smartPointerManager.removePointer(pointer1);
|
||||
assertTrue(removed1);
|
||||
assertNull(pointer1.getRange());
|
||||
}
|
||||
|
||||
public void testPointersRefCountSaturated() throws Exception {
|
||||
PsiFile file = configureByText(JavaFileType.INSTANCE, "class X{}");
|
||||
PsiClass aClass = ((PsiClassOwner)file).getClasses()[0];
|
||||
SmartPointerManagerImpl smartPointerManager = (SmartPointerManagerImpl)SmartPointerManager.getInstance(myProject);
|
||||
SmartPsiElementPointerImpl pointer1 = (SmartPsiElementPointerImpl)smartPointerManager.createSmartPsiElementPointer(aClass);
|
||||
for (int i=0; i<1000; i++) {
|
||||
SmartPsiElementPointer<PsiClass> pointer2 = smartPointerManager.createSmartPsiElementPointer(aClass);
|
||||
assertSame(pointer1, pointer2);
|
||||
}
|
||||
|
||||
assertNotNull(pointer1.getRange());
|
||||
assertEquals(Byte.MAX_VALUE, pointer1.incrementAndGetReferenceCount(0));
|
||||
|
||||
for (int i=0; i<1100; i++) {
|
||||
boolean removed1 = smartPointerManager.removePointer(pointer1);
|
||||
assertFalse(removed1);
|
||||
Assert.assertNotNull(pointer1.getRange());
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
-15
@@ -120,19 +120,25 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
|
||||
if (containingFile != null && !containingFile.isValid() || containingFile == null && !element.isValid()) {
|
||||
LOG.error("Invalid element:" + element);
|
||||
}
|
||||
SmartPointerEx<E> cachedPointer = getCachedPointer(element);
|
||||
if (cachedPointer != null) {
|
||||
SmartPointerEx<E> pointer = getCachedPointer(element);
|
||||
if (pointer != null) {
|
||||
containingFile = containingFile == null ? element.getContainingFile() : containingFile;
|
||||
if (containingFile != null && areBeltsFastened(containingFile)) {
|
||||
cachedPointer.fastenBelt(0, null);
|
||||
pointer.fastenBelt(0, null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
pointer = new SmartPsiElementPointerImpl<E>(myProject, element, containingFile);
|
||||
initPointer(pointer, containingFile);
|
||||
element.putUserData(CACHED_SMART_POINTER_KEY, new SoftReference<SmartPointerEx>(pointer));
|
||||
}
|
||||
if (pointer instanceof SmartPsiElementPointerImpl) {
|
||||
synchronized (lock) {
|
||||
((SmartPsiElementPointerImpl)pointer).incrementAndGetReferenceCount(1);
|
||||
}
|
||||
return cachedPointer;
|
||||
}
|
||||
|
||||
SmartPointerEx<E> pointer = new SmartPsiElementPointerImpl<E>(myProject, element, containingFile);
|
||||
initPointer(pointer, containingFile);
|
||||
element.putUserData(CACHED_SMART_POINTER_KEY, new SoftReference<SmartPointerEx>(pointer));
|
||||
return pointer;
|
||||
|
||||
}
|
||||
|
||||
private static <E extends PsiElement> SmartPointerEx<E> getCachedPointer(@NotNull E element) {
|
||||
@@ -178,14 +184,24 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
|
||||
@Override
|
||||
public boolean removePointer(@NotNull SmartPsiElementPointer pointer) {
|
||||
synchronized (lock) {
|
||||
PsiFile containingFile = pointer.getContainingFile();
|
||||
if (containingFile == null) return false;
|
||||
List<SmartPointerEx> pointers = getPointers(containingFile);
|
||||
if (pointers == null) return false;
|
||||
SmartPointerElementInfo info = ((SmartPsiElementPointerImpl)pointer).getElementInfo();
|
||||
info.cleanup();
|
||||
return pointers.remove(pointer);
|
||||
if (pointer instanceof SmartPsiElementPointerImpl) {
|
||||
int refCount = ((SmartPsiElementPointerImpl)pointer).incrementAndGetReferenceCount(-1);
|
||||
if (refCount == 0) {
|
||||
PsiElement element = ((SmartPointerEx)pointer).getCachedElement();
|
||||
if (element != null) {
|
||||
element.putUserData(CACHED_SMART_POINTER_KEY, null);
|
||||
}
|
||||
PsiFile containingFile = pointer.getContainingFile();
|
||||
if (containingFile == null) return false;
|
||||
List<SmartPointerEx> pointers = getPointers(containingFile);
|
||||
if (pointers == null) return false;
|
||||
SmartPointerElementInfo info = ((SmartPsiElementPointerImpl)pointer).getElementInfo();
|
||||
info.cleanup();
|
||||
return pointers.remove(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<SmartPointerEx> getPointers(@NotNull PsiFile containingFile) {
|
||||
|
||||
+6
@@ -39,6 +39,7 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
|
||||
private Reference<E> myElement;
|
||||
private final SmartPointerElementInfo myElementInfo;
|
||||
private final Class<? extends PsiElement> myElementClass;
|
||||
private byte myReferenceCount;
|
||||
|
||||
public SmartPsiElementPointerImpl(@NotNull Project project, @NotNull E element, @Nullable PsiFile containingFile) {
|
||||
this(element, createElementInfo(project, element, containingFile), element.getClass());
|
||||
@@ -193,4 +194,9 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
|
||||
}
|
||||
return Comparing.equal(pointer1.getElement(), pointer2.getElement());
|
||||
}
|
||||
|
||||
int incrementAndGetReferenceCount(int delta) {
|
||||
if (myReferenceCount == Byte.MAX_VALUE) return Byte.MAX_VALUE; // saturated
|
||||
return myReferenceCount += delta;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user