mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
unexpected gc in between passes
This commit is contained in:
@@ -143,7 +143,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
myInLibrary = fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile);
|
||||
|
||||
myRefCountHolder = RefCountHolder.endUsing(myFile);
|
||||
if (!myRefCountHolder.retrieveUnusedReferencesInfo(new Runnable() {
|
||||
if (myRefCountHolder == null || !myRefCountHolder.retrieveUnusedReferencesInfo(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean errorFound = collectHighlights(elementSet, highlights, progress);
|
||||
@@ -650,8 +650,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
|
||||
final PsiClass containingClass = member.getContainingClass();
|
||||
if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true;
|
||||
final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod();
|
||||
if (valuesMethod == null) return true;
|
||||
return isMethodReferenced(valuesMethod, progress, helper);
|
||||
return valuesMethod == null || isMethodReferenced(valuesMethod, progress, helper);
|
||||
}
|
||||
|
||||
private static boolean canBeReferencedViaWeirdNames(PsiMember member) {
|
||||
|
||||
@@ -28,7 +28,9 @@ import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.BidirectionalMap;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Iterator;
|
||||
@@ -65,17 +67,17 @@ public class RefCountHolder {
|
||||
|
||||
private void makeHardReachable(boolean isHard) {
|
||||
RefCountHolder holder = get();
|
||||
assert holder != null;
|
||||
assert !isHard || holder != null : "hard: "+isHard +"; holder="+holder;
|
||||
myHardRef = isHard ? holder : null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Key<HolderReference> REF_COUNT_HOLDER_IN_FILE_KEY = Key.create("REF_COUNT_HOLDER_IN_FILE_KEY");
|
||||
@NotNull
|
||||
private static Pair<RefCountHolder, HolderReference> getInstance(@NotNull PsiFile file) {
|
||||
private static Pair<RefCountHolder, HolderReference> getInstance(@NotNull PsiFile file, boolean create) {
|
||||
HolderReference ref = file.getUserData(REF_COUNT_HOLDER_IN_FILE_KEY);
|
||||
RefCountHolder holder = ref == null ? null : ref.get();
|
||||
if (holder == null) {
|
||||
if (holder == null && create) {
|
||||
holder = new RefCountHolder(file);
|
||||
HolderReference newRef = new HolderReference(holder);
|
||||
while (true) {
|
||||
@@ -97,21 +99,26 @@ public class RefCountHolder {
|
||||
|
||||
@NotNull
|
||||
public static RefCountHolder startUsing(@NotNull PsiFile file) {
|
||||
Pair<RefCountHolder, HolderReference> pair = getInstance(file);
|
||||
Pair<RefCountHolder, HolderReference> pair = getInstance(file, true);
|
||||
HolderReference reference = pair.second;
|
||||
reference.makeHardReachable(true); // make sure RefCountHolder won't be gced during highlighting
|
||||
log("startUsing: " + pair.first.myState+" for "+file);
|
||||
return pair.first;
|
||||
}
|
||||
@NotNull
|
||||
|
||||
@Nullable("might be gced")
|
||||
public static RefCountHolder endUsing(@NotNull PsiFile file) {
|
||||
Pair<RefCountHolder, HolderReference> pair = getInstance(file);
|
||||
Pair<RefCountHolder, HolderReference> pair = getInstance(file, false);
|
||||
HolderReference reference = pair.second;
|
||||
reference.makeHardReachable(false); // no longer needed, can be cleared
|
||||
return pair.first;
|
||||
RefCountHolder holder = pair.first;
|
||||
log("endUsing: " + (holder == null ? null : holder.myState)+" for "+file);
|
||||
return holder;
|
||||
}
|
||||
|
||||
private RefCountHolder(@NotNull PsiFile file) {
|
||||
myFile = file;
|
||||
log("c: created: " + myState.get()+" for "+file);
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
@@ -267,10 +274,13 @@ public class RefCountHolder {
|
||||
}
|
||||
|
||||
public boolean analyze(@NotNull PsiFile file, TextRange dirtyScope, @NotNull Runnable analyze) {
|
||||
State old = myState.get();
|
||||
myState.compareAndSet(State.READY, State.VIRGIN);
|
||||
if (!myState.compareAndSet(State.VIRGIN, State.BEING_WRITTEN_BY_GHP)) {
|
||||
log("a: failed to change " + old + "->" + State.BEING_WRITTEN_BY_GHP);
|
||||
return false;
|
||||
}
|
||||
log("a: changed " + old + "->" + State.BEING_WRITTEN_BY_GHP);
|
||||
boolean finished = false;
|
||||
try {
|
||||
if (dirtyScope != null) {
|
||||
@@ -288,20 +298,29 @@ public class RefCountHolder {
|
||||
finally {
|
||||
boolean set = myState.compareAndSet(State.BEING_WRITTEN_BY_GHP, finished ? State.READY : State.VIRGIN);
|
||||
assert set : myState.get();
|
||||
log("a: changed back " + State.BEING_WRITTEN_BY_GHP + "->" + (finished ? State.READY : State.VIRGIN));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void log(@NonNls String s) {
|
||||
//System.err.println("RFC: "+s);
|
||||
}
|
||||
|
||||
public boolean retrieveUnusedReferencesInfo(@NotNull Runnable analyze) {
|
||||
State old = myState.get();
|
||||
if (!myState.compareAndSet(State.READY, State.BEING_USED_BY_PHP)) {
|
||||
log("r: failed to change " + old + "->" + State.BEING_USED_BY_PHP);
|
||||
return false;
|
||||
}
|
||||
log("r: changed " + old + "->" + State.BEING_USED_BY_PHP);
|
||||
try {
|
||||
analyze.run();
|
||||
}
|
||||
finally {
|
||||
boolean set = myState.compareAndSet(State.BEING_USED_BY_PHP, State.READY);
|
||||
assert set : myState.get();
|
||||
log("r: changed back " + State.BEING_USED_BY_PHP + "->" + State.READY);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+71
-94
@@ -84,6 +84,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass");
|
||||
static final String PRESENTABLE_NAME = DaemonBundle.message("pass.syntax");
|
||||
private static final Key<Boolean> HAS_ERROR_ELEMENT = Key.create("HAS_ERROR_ELEMENT");
|
||||
private static final JobLauncher JobUtil = JobLauncher.getInstance();
|
||||
|
||||
private final int myStartOffset;
|
||||
private final int myEndOffset;
|
||||
@@ -101,9 +102,8 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
return o1.order() - o2.order();
|
||||
}
|
||||
};
|
||||
private Runnable myApplyCommand;
|
||||
private volatile Runnable myApplyCommand;
|
||||
private final EditorColorsScheme myGlobalScheme;
|
||||
private boolean myFailFastOnAcquireReadAction = true;
|
||||
|
||||
public GeneralHighlightingPass(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@@ -320,15 +320,17 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!JobLauncher.getInstance().invokeConcurrentlyUnderProgress(new ArrayList<PsiElement>(hosts), progress, false,
|
||||
new Processor<PsiElement>() {
|
||||
@Override
|
||||
public boolean process(PsiElement element) {
|
||||
progress.checkCanceled();
|
||||
InjectedLanguageFacadeImpl.enumerate(element, myFile, false, visitor);
|
||||
return true;
|
||||
}
|
||||
})) throw new ProcessCanceledException();
|
||||
if (!JobUtil.invokeConcurrentlyUnderProgress(new ArrayList<PsiElement>(hosts), progress, false,
|
||||
new Processor<PsiElement>() {
|
||||
@Override
|
||||
public boolean process(PsiElement element) {
|
||||
progress.checkCanceled();
|
||||
InjectedLanguageFacadeImpl.enumerate(element, myFile, false, visitor);
|
||||
return true;
|
||||
}
|
||||
})) {
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
}
|
||||
|
||||
// returns false if canceled
|
||||
@@ -339,86 +341,65 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(myProject);
|
||||
final TextAttributes injectedAttributes = myGlobalScheme.getAttributes(EditorColors.INJECTED_LANGUAGE_FRAGMENT);
|
||||
|
||||
return JobLauncher.getInstance().invokeConcurrentlyUnderProgress(new ArrayList<PsiFile>(injectedFiles), progress,
|
||||
myFailFastOnAcquireReadAction,
|
||||
new Processor<PsiFile>() {
|
||||
@Override
|
||||
public boolean process(final PsiFile injectedPsi) {
|
||||
DocumentWindow documentWindow =
|
||||
(DocumentWindow)PsiDocumentManager.getInstance(myProject)
|
||||
.getCachedDocument(injectedPsi);
|
||||
if (documentWindow == null) return true;
|
||||
Place places = InjectedLanguageFacadeImpl.getShreds(injectedPsi);
|
||||
for (PsiLanguageInjectionHost.Shred place : places) {
|
||||
TextRange textRange = place.getRangeInsideHost()
|
||||
.shiftRight(place.getHost().getTextRange().getStartOffset());
|
||||
if (textRange.isEmpty()) continue;
|
||||
String desc =
|
||||
injectedPsi.getLanguage().getDisplayName() +
|
||||
": " +
|
||||
injectedPsi.getText();
|
||||
HighlightInfo info = HighlightInfo
|
||||
.createHighlightInfo(
|
||||
HighlightInfoType.INJECTED_LANGUAGE_BACKGROUND,
|
||||
textRange, null, desc, injectedAttributes);
|
||||
info.fromInjection = true;
|
||||
outInfos.add(info);
|
||||
}
|
||||
return JobUtil.invokeConcurrentlyUnderProgress(new ArrayList<PsiFile>(injectedFiles), progress, isFailFastOnAcquireReadAction(),
|
||||
new Processor<PsiFile>() {
|
||||
@Override
|
||||
public boolean process(final PsiFile injectedPsi) {
|
||||
DocumentWindow documentWindow = (DocumentWindow)PsiDocumentManager.getInstance(myProject).getCachedDocument(injectedPsi);
|
||||
if (documentWindow == null) return true;
|
||||
Place places = InjectedLanguageFacadeImpl.getShreds(injectedPsi);
|
||||
for (PsiLanguageInjectionHost.Shred place : places) {
|
||||
TextRange textRange = place.getRangeInsideHost().shiftRight(place.getHost().getTextRange().getStartOffset());
|
||||
if (textRange.isEmpty()) continue;
|
||||
String desc = injectedPsi.getLanguage().getDisplayName() + ": " + injectedPsi.getText();
|
||||
HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_BACKGROUND,
|
||||
textRange, null, desc, injectedAttributes);
|
||||
info.fromInjection = true;
|
||||
outInfos.add(info);
|
||||
}
|
||||
|
||||
HighlightInfoHolder holder = createInfoHolder(injectedPsi);
|
||||
runHighlightVisitorsForInjected(injectedPsi, holder, progress);
|
||||
for (int i = 0; i < holder.size(); i++) {
|
||||
HighlightInfo info = holder.get(i);
|
||||
final int startOffset =
|
||||
documentWindow.injectedToHost(info.startOffset);
|
||||
final TextRange fixedTextRange =
|
||||
getFixedTextRange(documentWindow, startOffset);
|
||||
addPatchedInfos(info, injectedPsi, documentWindow,
|
||||
injectedLanguageManager,
|
||||
fixedTextRange, outInfos);
|
||||
}
|
||||
holder.clear();
|
||||
highlightInjectedSyntax(injectedPsi, holder);
|
||||
for (int i = 0; i < holder.size(); i++) {
|
||||
HighlightInfo info = holder.get(i);
|
||||
final int startOffset = info.startOffset;
|
||||
final TextRange fixedTextRange =
|
||||
getFixedTextRange(documentWindow, startOffset);
|
||||
if (fixedTextRange == null) {
|
||||
info.fromInjection = true;
|
||||
outInfos.add(info);
|
||||
}
|
||||
else {
|
||||
HighlightInfo patched =
|
||||
new HighlightInfo(info.forcedTextAttributes,
|
||||
info.forcedTextAttributesKey,
|
||||
info.type,
|
||||
fixedTextRange.getStartOffset(),
|
||||
fixedTextRange.getEndOffset(),
|
||||
info.description, info.toolTip,
|
||||
info.type.getSeverity(null),
|
||||
info.isAfterEndOfLine, null,
|
||||
false);
|
||||
patched.fromInjection = true;
|
||||
outInfos.add(patched);
|
||||
}
|
||||
}
|
||||
HighlightInfoHolder holder = createInfoHolder(injectedPsi);
|
||||
runHighlightVisitorsForInjected(injectedPsi, holder, progress);
|
||||
for (int i = 0; i < holder.size(); i++) {
|
||||
HighlightInfo info = holder.get(i);
|
||||
final int startOffset = documentWindow.injectedToHost(info.startOffset);
|
||||
final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
|
||||
addPatchedInfos(info, injectedPsi, documentWindow, injectedLanguageManager, fixedTextRange, outInfos);
|
||||
}
|
||||
holder.clear();
|
||||
highlightInjectedSyntax(injectedPsi, holder);
|
||||
for (int i = 0; i < holder.size(); i++) {
|
||||
HighlightInfo info = holder.get(i);
|
||||
final int startOffset = info.startOffset;
|
||||
final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
|
||||
if (fixedTextRange == null) {
|
||||
info.fromInjection = true;
|
||||
outInfos.add(info);
|
||||
}
|
||||
else {
|
||||
HighlightInfo patched = new HighlightInfo(info.forcedTextAttributes, info.forcedTextAttributesKey,
|
||||
info.type, fixedTextRange.getStartOffset(), fixedTextRange.getEndOffset(),
|
||||
info.description, info.toolTip, info.type.getSeverity(null),
|
||||
info.isAfterEndOfLine, null, false);
|
||||
patched.fromInjection = true;
|
||||
outInfos.add(patched);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDumbMode()) {
|
||||
List<HighlightInfo> todos = new ArrayList<HighlightInfo>();
|
||||
highlightTodos(injectedPsi, injectedPsi.getText(), 0,
|
||||
injectedPsi.getTextLength(), progress,
|
||||
myPriorityRange, todos,
|
||||
todos);
|
||||
for (HighlightInfo info : todos) {
|
||||
addPatchedInfos(info, injectedPsi, documentWindow,
|
||||
injectedLanguageManager,
|
||||
null, outInfos);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!isDumbMode()) {
|
||||
List<HighlightInfo> todos = new ArrayList<HighlightInfo>();
|
||||
highlightTodos(injectedPsi, injectedPsi.getText(), 0, injectedPsi.getTextLength(), progress, myPriorityRange, todos, todos);
|
||||
for (HighlightInfo info : todos) {
|
||||
addPatchedInfos(info, injectedPsi, documentWindow, injectedLanguageManager, null, outInfos);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected boolean isFailFastOnAcquireReadAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static TextRange getFixedTextRange(@NotNull DocumentWindow documentWindow, int startOffset) {
|
||||
@@ -789,7 +770,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
return visitorArray;
|
||||
}
|
||||
|
||||
static void cancelAndRestartDaemonLater(ProgressIndicator progress, final Project project, TextEditorHighlightingPass pass) {
|
||||
static void cancelAndRestartDaemonLater(ProgressIndicator progress, final Project project, TextEditorHighlightingPass pass) throws ProcessCanceledException {
|
||||
PassExecutorService.log(progress, pass, "Cancel and restart");
|
||||
progress.cancel();
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@@ -893,8 +874,4 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
public String toString() {
|
||||
return super.toString() + " updateAll="+myUpdateAll+" range=("+myStartOffset+","+myEndOffset+")";
|
||||
}
|
||||
|
||||
public void setFailFastOnAcquireReadAction(boolean failFastOnAcquireReadAction) {
|
||||
myFailFastOnAcquireReadAction = failFastOnAcquireReadAction;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -192,8 +192,12 @@ public abstract class DefaultHighlightVisitorBasedInspection extends GlobalSimpl
|
||||
@NotNull ProgressIndicator progress) {
|
||||
// do not mess with real editor highlights
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isFailFastOnAcquireReadAction() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
pass.setFailFastOnAcquireReadAction(false);
|
||||
DaemonProgressIndicator progress = new DaemonProgressIndicator();
|
||||
progress.start();
|
||||
pass.collectInformation(progress);
|
||||
|
||||
Reference in New Issue
Block a user