mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
EA-56355 - assert: PrioritizedDocumentListener$.getPriority; fix racey list.toArray(new T[list.size()])
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.
|
||||
@@ -17,7 +17,9 @@
|
||||
package com.intellij.lang;
|
||||
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -53,7 +55,8 @@ public class CompositeLanguage extends Language {
|
||||
return extensions.toArray(new Language[extensions.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LanguageFilter[] getLanguageExtensions() {
|
||||
return myFilters.toArray(new LanguageFilter[myFilters.size()]);
|
||||
return ArrayUtil.stripTrailingNulls(myFilters.toArray(new LanguageFilter[myFilters.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,7 @@ import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.DocumentUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntArrayList;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
@@ -945,7 +942,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
|
||||
private DocumentListener[] getCachedListeners() {
|
||||
DocumentListener[] cachedListeners = myCachedDocumentListeners.get();
|
||||
if (cachedListeners == null) {
|
||||
DocumentListener[] listeners = myDocumentListeners.toArray(new DocumentListener[myDocumentListeners.size()]);
|
||||
DocumentListener[] listeners = ArrayUtil.stripTrailingNulls(myDocumentListeners.toArray(new DocumentListener[myDocumentListeners.size()]));
|
||||
Arrays.sort(listeners, PrioritizedDocumentListener.COMPARATOR);
|
||||
cachedListeners = listeners;
|
||||
myCachedDocumentListeners.set(cachedListeners);
|
||||
|
||||
+4
-5
@@ -189,12 +189,11 @@ public class VirtualFilePointerContainerImpl extends TraceableDisposable impleme
|
||||
result = EMPTY;
|
||||
}
|
||||
else {
|
||||
VirtualFilePointer[] vf = myList.toArray(new VirtualFilePointer[myList.size()]);
|
||||
List<VirtualFile> cachedFiles = new ArrayList<VirtualFile>(vf.length);
|
||||
List<String> cachedUrls = new ArrayList<String>(vf.length);
|
||||
List<VirtualFile> cachedDirectories = new ArrayList<VirtualFile>(vf.length / 3);
|
||||
List<VirtualFile> cachedFiles = new ArrayList<VirtualFile>(myList.size());
|
||||
List<String> cachedUrls = new ArrayList<String>(myList.size());
|
||||
List<VirtualFile> cachedDirectories = new ArrayList<VirtualFile>(myList.size() / 3);
|
||||
boolean allFilesAreDirs = true;
|
||||
for (VirtualFilePointer v : vf) {
|
||||
for (VirtualFilePointer v : myList) {
|
||||
VirtualFile file = v.getFile();
|
||||
String url = v.getUrl();
|
||||
cachedUrls.add(url);
|
||||
|
||||
@@ -43,10 +43,7 @@ import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import com.intellij.psi.impl.source.text.BlockSupportImpl;
|
||||
import com.intellij.psi.text.BlockSupport;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.FileContentUtilCore;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
@@ -574,7 +571,8 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
@NotNull
|
||||
public Document[] getUncommittedDocuments() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
return myUncommittedDocuments.toArray(new Document[myUncommittedDocuments.size()]);
|
||||
Document[] documents = myUncommittedDocuments.toArray(new Document[myUncommittedDocuments.size()]);
|
||||
return ArrayUtil.stripTrailingNulls(documents);
|
||||
}
|
||||
|
||||
boolean isInUncommittedSet(@NotNull Document document) {
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.
|
||||
@@ -37,6 +37,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -248,7 +249,7 @@ public class IntentionManagerImpl extends IntentionManager {
|
||||
@Override
|
||||
@NotNull
|
||||
public IntentionAction[] getIntentionActions() {
|
||||
return myActions.toArray(new IntentionAction[myActions.size()]);
|
||||
return ArrayUtil.stripTrailingNulls(myActions.toArray(new IntentionAction[myActions.size()]));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ProjectManagerAdapter;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -241,7 +242,7 @@ public class EditorFactoryImpl extends EditorFactory implements ApplicationCompo
|
||||
@Override
|
||||
@NotNull
|
||||
public Editor[] getAllEditors() {
|
||||
return myEditors.toArray(new Editor[myEditors.size()]);
|
||||
return ArrayUtil.stripTrailingNulls(myEditors.toArray(new Editor[myEditors.size()]));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@@ -853,4 +854,18 @@ public class ArrayUtil extends ArrayUtilRt {
|
||||
dst[i++] = t;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> T[] stripTrailingNulls(T[] array) {
|
||||
return array.length != 0 && array[array.length-1] == null ? Arrays.copyOf(array, trailingNullsIndex(array)) : array;
|
||||
}
|
||||
|
||||
private static <T> int trailingNullsIndex(T[] array) {
|
||||
for (int i=array.length-1; i>=0; i--) {
|
||||
if (array[i] != null) {
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2242,6 +2242,9 @@ public class ContainerUtil extends ContainerUtilRt {
|
||||
* - faster modification in the uncontended case
|
||||
* - less memory
|
||||
* - slower modification in highly contented case (which is the kind of situation you shouldn't use COWAL anyway)
|
||||
*
|
||||
* N.B. Avoid using <code>list.toArray(new T[list.size()])</code> on this list because it is inherently racey and
|
||||
* therefore can return array with null elements at the end.
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(pure=true)
|
||||
@@ -2330,6 +2333,9 @@ public class ContainerUtil extends ContainerUtilRt {
|
||||
return new ConcurrentWeakHashMap<K, V>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {@link #createLockFreeCopyOnWriteList()}
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(pure=true)
|
||||
public static <T> ConcurrentList<T> createConcurrentList() {
|
||||
|
||||
+2
-4
@@ -287,15 +287,13 @@ public class CvsEntriesManager extends VirtualFileAdapter {
|
||||
}
|
||||
|
||||
private void onEntriesChanged(final VirtualFile parent) {
|
||||
final CvsEntriesListener[] listeners = myEntriesListeners.toArray(new CvsEntriesListener[myEntriesListeners.size()]);
|
||||
for (CvsEntriesListener listener : listeners) {
|
||||
for (CvsEntriesListener listener : myEntriesListeners) {
|
||||
listener.entriesChanged(parent);
|
||||
}
|
||||
}
|
||||
|
||||
private void onEntryChanged(final VirtualFile file) {
|
||||
final CvsEntriesListener[] listeners = myEntriesListeners.toArray(new CvsEntriesListener[myEntriesListeners.size()]);
|
||||
for (CvsEntriesListener listener : listeners) {
|
||||
for (CvsEntriesListener listener : myEntriesListeners) {
|
||||
listener.entryChanged(file);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user