From 9414e45716cb427bbda098c4be7d2fde8a37b74a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 7 Feb 2011 10:33:14 +0300 Subject: [PATCH] migrate to TransferToEdtQueue --- .../HighlightSuppressedWarningsHandler.java | 6 +- .../daemon/impl/DaemonCodeAnalyzerImpl.java | 3 +- .../daemon/impl/LocalInspectionsPass.java | 147 +++++++++--------- .../impl/LocalInspectionsPassFactory.java | 2 +- .../WholeFileLocalInspectionsPassFactory.java | 2 +- .../ex/GlobalInspectionContextImpl.java | 5 +- .../impl/TransferToPooledThreadQueue.java | 40 +++++ .../vfs/encoding/EncodingManagerImpl.java | 44 ++---- .../testFramework/LightPlatformTestCase.java | 2 +- .../usages/impl/UsageViewMemoryTest.java | 58 +++++++ .../util/xml/ui/DomUIFactoryImpl.java | 3 +- 11 files changed, 198 insertions(+), 114 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/application/impl/TransferToPooledThreadQueue.java create mode 100644 platform/usageView/testSrc/com/intellij/usages/impl/UsageViewMemoryTest.java diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java index 731956ee956d..6022b512656a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java @@ -108,7 +108,9 @@ public class HighlightSuppressedWarningsHandler extends HighlightUsagesHandlerBa public void computeUsages(List targets) { final Project project = myTarget.getProject(); final PsiElement parent = myTarget.getParent().getParent(); - final LocalInspectionsPass pass = new LocalInspectionsPass(myFile, myFile.getViewProvider().getDocument(), parent.getTextRange().getStartOffset(), parent.getTextRange().getEndOffset()); + final LocalInspectionsPass pass = new LocalInspectionsPass(myFile, myFile.getViewProvider().getDocument(), + parent.getTextRange().getStartOffset(), parent.getTextRange().getEndOffset(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, + false); final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); for (PsiLiteralExpression target : targets) { @@ -128,7 +130,7 @@ public class HighlightSuppressedWarningsHandler extends HighlightUsagesHandlerBa ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); Runnable inspect = new Runnable() { public void run() { - pass.doInspectInBatch(managerEx, Collections.singletonList(tool), false); + pass.doInspectInBatch(managerEx, Collections.singletonList(tool)); } }; if (indicator == null) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index 832fb318eab1..8a665afa2fa4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -159,7 +159,8 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx List result = new ArrayList(); result.addAll(action1.getHighlights()); - LocalInspectionsPass action3 = new LocalInspectionsPass(psiFile, document, 0, psiFile.getTextLength()); + LocalInspectionsPass action3 = new LocalInspectionsPass(psiFile, document, 0, + psiFile.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true); action3.doCollectInformation(progress); result.addAll(action3.getHighlights()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index 503cd00a3c53..76a6ce8f008b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -46,7 +46,6 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.Trinity; import com.intellij.openapi.util.text.StringUtil; @@ -58,7 +57,7 @@ import com.intellij.util.ConcurrencyUtil; import com.intellij.util.Function; import com.intellij.util.Processor; import com.intellij.util.containers.ConcurrentHashMap; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.containers.TransferToEDTQueue; import com.intellij.xml.util.XmlStringUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; @@ -67,9 +66,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicBoolean; /** * @author max @@ -77,9 +74,11 @@ import java.util.concurrent.atomic.AtomicBoolean; public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass implements DumbAware { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.LocalInspectionsPass"); private static final int NUM_ELEMENTS_PER_CHECK_CANCELLED = 5; + public static final TextRange EMPTY_PRIORITY_RANGE = new TextRange(0, 0); private final int myStartOffset; private final int myEndOffset; private final TextRange myPriorityRange; + private final boolean myIgnoreSuppressed; private final ConcurrentMap> result = new ConcurrentHashMap>(); static final String PRESENTABLE_NAME = DaemonBundle.message("pass.inspection"); private volatile List myInfos = Collections.emptyList(); @@ -88,14 +87,17 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass private final InspectionProfileWrapper myProfileWrapper; private boolean myFailFastOnAcquireReadAction; - public LocalInspectionsPass(@NotNull PsiFile file, @Nullable Document document, int startOffset, int endOffset) { - this(file, document, startOffset, endOffset, new TextRange(0, 0)); - } - public LocalInspectionsPass(@NotNull PsiFile file, @Nullable Document document, int startOffset, int endOffset, @NotNull TextRange priorityRange) { + public LocalInspectionsPass(@NotNull PsiFile file, + @Nullable Document document, + int startOffset, + int endOffset, + @NotNull TextRange priorityRange, + boolean ignoreSuppressed) { super(file.getProject(), document, PRESENTABLE_NAME, file, true); myStartOffset = startOffset; myEndOffset = endOffset; myPriorityRange = priorityRange; + myIgnoreSuppressed = ignoreSuppressed; setId(Pass.LOCAL_INSPECTIONS); final KeymapManager keymapManager = KeymapManager.getInstance(); @@ -113,7 +115,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass if (customizationStrategy != null) { profileToUse = customizationStrategy.fun(profileToUse); } - + myProfileWrapper = profileToUse; mySeverityRegistrar = ((SeverityProvider)myProfileWrapper.getInspectionProfile().getProfileManager()).getSeverityRegistrar(); LOG.assertTrue(mySeverityRegistrar != null); @@ -128,7 +130,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass final InspectionManagerEx iManager = (InspectionManagerEx)InspectionManager.getInstance(myProject); final InspectionProfileWrapper profile = myProfileWrapper; final List tools = DumbService.getInstance(myProject).filterByDumbAwareness(getInspectionTools(profile)); - inspect(tools, iManager, true, true, true, progress); + inspect(tools, iManager, true, true, progress); } finally { disposeDescriptors(); @@ -146,7 +148,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass result.clear(); } - public void doInspectInBatch(final InspectionManagerEx iManager, List toolWrappers, boolean ignoreSuppressed) { + public void doInspectInBatch(final InspectionManagerEx iManager, List toolWrappers) { Map tool2Wrapper = new THashMap(toolWrappers.size()); for (InspectionProfileEntry toolWrapper : toolWrappers) { tool2Wrapper.put(((LocalInspectionToolWrapper)toolWrapper).getTool(), (LocalInspectionToolWrapper)toolWrapper); @@ -154,7 +156,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass List tools = new ArrayList(tool2Wrapper.keySet()); ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); - inspect(tools, iManager, false, ignoreSuppressed, false, progress); + inspect(tools, iManager, false, false, progress); addDescriptorsFromInjectedResults(tool2Wrapper, iManager); List resultList = result.get(myFile); if (resultList == null) return; @@ -163,7 +165,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass LocalInspectionToolWrapper toolWrapper = tool2Wrapper.get(tool); if (toolWrapper == null) continue; for (ProblemDescriptor descriptor : inspectionResult.foundProblems) { - toolWrapper.addProblemDescriptors(Collections.singletonList(descriptor), ignoreSuppressed); + toolWrapper.addProblemDescriptors(Collections.singletonList(descriptor), myIgnoreSuppressed); } } } @@ -214,7 +216,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass private void inspect(final List tools, final InspectionManagerEx iManager, final boolean isOnTheFly, - final boolean ignoreSuppressed, boolean failFastOnAcquireReadAction, @NotNull final ProgressIndicator indicator) { myFailFastOnAcquireReadAction = failFastOnAcquireReadAction; @@ -231,8 +232,8 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass List> init = new ArrayList>(); boolean finished = false; try { - visitPriorityElementsAndInit(tools, iManager, isOnTheFly, ignoreSuppressed, indicator, inside, session, init); - visitRestElementsAndCleanup(tools,iManager,isOnTheFly,ignoreSuppressed, indicator, outside, session, init); + visitPriorityElementsAndInit(tools, iManager, isOnTheFly, indicator, inside, session, init); + visitRestElementsAndCleanup(tools,iManager,isOnTheFly, indicator, outside, session, init); finished = true; } finally { @@ -253,13 +254,12 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass indicator.checkCanceled(); myInfos = new ArrayList(); - addHighlightsFromResults(myInfos, ignoreSuppressed); + addHighlightsFromResults(myInfos); } private void visitPriorityElementsAndInit(@NotNull List tools, @NotNull final InspectionManagerEx iManager, final boolean isOnTheFly, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator, @NotNull final List elements, @NotNull final LocalInspectionToolSession session, @@ -276,7 +276,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass public void registerProblem(@NotNull ProblemDescriptor descriptor) { super.registerProblem(descriptor); if (applyIncrementally[0]) { - addDescriptorIncrementally(descriptor, tool, ignoreSuppressed, indicator); + addDescriptorIncrementally(descriptor, tool, indicator); } } }; @@ -295,7 +295,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } }, myFailFastOnAcquireReadAction, indicator); if (!result) throw new ProcessCanceledException(); - inspectInjectedPsi(elements, tools, isOnTheFly, ignoreSuppressed, indicator, iManager, true); + inspectInjectedPsi(elements, tools, isOnTheFly, indicator, iManager, true); } private static PsiElementVisitor createVisitorAndAcceptElements(@NotNull LocalInspectionTool tool, @@ -324,7 +324,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass private void visitRestElementsAndCleanup(@NotNull List tools, @NotNull InspectionManagerEx iManager, final boolean isOnTheFly, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator, @NotNull final List elements, @NotNull final LocalInspectionToolSession session, @@ -341,7 +340,8 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass ProblemsHolder holder = trinity.second; PsiElementVisitor elementVisitor = trinity.third; for (int i = 0, elementsSize = elements.size(); i < elementsSize; i++) { - elements.get(i).accept(elementVisitor); + PsiElement element = elements.get(i); + element.accept(elementVisitor); if (i % NUM_ELEMENTS_PER_CHECK_CANCELLED == 0) indicator.checkCanceled(); } @@ -359,13 +359,12 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass if (!result) { throw new ProcessCanceledException(); } - inspectInjectedPsi(elements, tools, isOnTheFly, ignoreSuppressed, indicator, iManager, false); + inspectInjectedPsi(elements, tools, isOnTheFly, indicator, iManager, false); } private void inspectInjectedPsi(@NotNull final List elements, @NotNull final List tools, final boolean onTheFly, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator, @NotNull final InspectionManagerEx iManager, final boolean inVisibleRange) { @@ -380,7 +379,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass if (injected.isEmpty()) return; if (!JobUtil.invokeConcurrentlyUnderProgress(new ArrayList(injected), new Processor() { public boolean process(final PsiFile injectedPsi) { - doInspectInjectedPsi(injectedPsi, tools, onTheFly, ignoreSuppressed, indicator, iManager, inVisibleRange); + doInspectInjectedPsi(injectedPsi, tools, onTheFly, indicator, iManager, inVisibleRange); return true; } }, myFailFastOnAcquireReadAction, indicator)) throw new ProcessCanceledException(); @@ -389,7 +388,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass public Collection getHighlights() { List highlights = new ArrayList(); - addHighlightsFromResults(highlights, true); + addHighlightsFromResults(highlights); return highlights; } @@ -410,56 +409,52 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass severity, problemDescriptor.isAfterEndOfLine(), null, isFileLevel); } - private final AtomicBoolean haveInfosToProcess = new AtomicBoolean(); - private final ConcurrentLinkedQueue> infosToAdd = new ConcurrentLinkedQueue>(); + private final TransferToEDTQueue> myTransferToEDTQueue; + { + myTransferToEDTQueue = + new TransferToEDTQueue>(new Processor>() { + private final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); + private final InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject); + private final List infos = new ArrayList(2); + private final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); + @Override + public boolean process(Trinity trinity) { + ProgressIndicator indicator = trinity.getThird(); + if (indicator.isCanceled()) { + return false; + } + + ProblemDescriptor descriptor = trinity.first; + LocalInspectionTool tool = trinity.second; + PsiElement psiElement = descriptor.getPsiElement(); + if (psiElement == null) return true; + PsiFile file = psiElement.getContainingFile(); + Document thisDocument = documentManager.getDocument(file); + + HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); + + infos.clear(); + createHighlightsForDescriptor(infos, emptyActionRegistered, ilManager, file, thisDocument, tool, severity, descriptor); + for (HighlightInfo info : infos) { + final EditorColorsScheme colorsScheme = getColorsScheme(); + UpdateHighlightersUtil.addHighlighterToEditorIncrementally(myProject, myDocument, myFile, myStartOffset, myEndOffset, + info, colorsScheme, getId()); + } + + return true; + } + }, myProject.getDisposed()); + } + private final Set emptyActionRegistered = Collections.synchronizedSet(new HashSet()); private void addDescriptorIncrementally(@NotNull final ProblemDescriptor descriptor, @NotNull final LocalInspectionTool tool, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator) { - if (ignoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(descriptor.getPsiElement(), tool)) { + if (myIgnoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(descriptor.getPsiElement(), tool)) { return; } - - infosToAdd.offer(Pair.create(descriptor, tool)); - if (haveInfosToProcess.getAndSet(true)) return; - final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); - // extra invoke later is harmless, missing invoke is not - UIUtil.invokeLaterIfNeeded(new Runnable() { - public void run() { - if (myProject.isDisposed()) return; - InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); - InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject); - List infos = new ArrayList(2); - while (haveInfosToProcess.compareAndSet(true, false)) { - for (Pair pair = infosToAdd.poll(); pair != null; pair = infosToAdd.poll()) { - if (indicator.isCanceled()) { - infosToAdd.clear(); - return; - } - - ProblemDescriptor descriptor = pair.first; - LocalInspectionTool tool = pair.second; - PsiElement psiElement = descriptor.getPsiElement(); - if (psiElement == null) continue; - PsiFile file = psiElement.getContainingFile(); - Document thisDocument = documentManager.getDocument(file); - - HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); - - infos.clear(); - createHighlightsForDescriptor(infos, emptyActionRegistered, ilManager, file, thisDocument, tool, severity, descriptor, ignoreSuppressed); - for (HighlightInfo info : infos) { - final EditorColorsScheme colorsScheme = getColorsScheme(); - - UpdateHighlightersUtil.addHighlighterToEditorIncrementally(myProject, myDocument, myFile, myStartOffset, myEndOffset, - info, colorsScheme, getId()); - } - } - } - } - }); + myTransferToEDTQueue.offer(Trinity.create(descriptor, tool, indicator)); } private void appendDescriptors(PsiFile file, List descriptors, LocalInspectionTool tool) { @@ -519,7 +514,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myInfos, getColorsScheme(), getId()); } - private void addHighlightsFromResults(final List outInfos, boolean ignoreSuppressed) { + private void addHighlightsFromResults(final List outInfos) { InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject); @@ -534,8 +529,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass LocalInspectionTool tool = inspectionResult.tool; HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); for (ProblemDescriptor descriptor : inspectionResult.foundProblems) { - createHighlightsForDescriptor(outInfos, emptyActionRegistered, ilManager, file, documentRange, tool, severity, descriptor, - ignoreSuppressed); + createHighlightsForDescriptor(outInfos, emptyActionRegistered, ilManager, file, documentRange, tool, severity, descriptor); } } } @@ -548,10 +542,10 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass Document documentRange, LocalInspectionTool tool, HighlightSeverity severity, - ProblemDescriptor descriptor, boolean ignoreSuppressed) { + ProblemDescriptor descriptor) { PsiElement psiElement = descriptor.getPsiElement(); if (psiElement == null) return; - if (ignoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(psiElement, tool)) return; + if (myIgnoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(psiElement, tool)) return; HighlightInfoType level = highlightTypeFromDescriptor(descriptor, severity); HighlightInfo info = createHighlightInfo(descriptor, tool, level, emptyActionRegistered); if (info == null) return; @@ -677,7 +671,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass private void doInspectInjectedPsi(@NotNull PsiFile injectedPsi, @NotNull List tools, final boolean isOnTheFly, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator, @NotNull InspectionManagerEx iManager, final boolean inVisibleRange) { @@ -689,7 +682,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } for (final LocalInspectionTool tool : tools) { indicator.checkCanceled(); - if (host != null && ignoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(host, tool)) { + if (host != null && myIgnoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(host, tool)) { continue; } ProblemsHolder holder = new ProblemsHolder(iManager, injectedPsi, isOnTheFly) { @@ -697,7 +690,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass public void registerProblem(@NotNull ProblemDescriptor descriptor) { super.registerProblem(descriptor); if (isOnTheFly && inVisibleRange) { - addDescriptorIncrementally(descriptor, tool, ignoreSuppressed, indicator); + addDescriptorIncrementally(descriptor, tool, indicator); } } }; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPassFactory.java index 327772a905a3..368be146dd9b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPassFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPassFactory.java @@ -55,7 +55,7 @@ public class LocalInspectionsPassFactory extends AbstractProjectComponent implem if (textRange == null) return new ProgressableTextEditorHighlightingPass.EmptyPass(myProject, editor.getDocument() ); TextRange visibleRange = VisibleHighlightingPassFactory.calculateVisibleRange(editor); - return new LocalInspectionsPass(file, editor.getDocument(), textRange.getStartOffset(), textRange.getEndOffset(), visibleRange){ + return new LocalInspectionsPass(file, editor.getDocument(), textRange.getStartOffset(), textRange.getEndOffset(), visibleRange, true){ List getInspectionTools(InspectionProfileWrapper profile) { List tools = super.getInspectionTools(profile); List result = new ArrayList(tools.size()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java index c77f7236f3e3..2216b24dcbcf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java @@ -90,7 +90,7 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone public TextEditorHighlightingPass createHighlightingPass(@NotNull final PsiFile file, @NotNull final Editor editor) { TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.LOCAL_INSPECTIONS); if (textRange == null || myFileTools.containsKey(file) && !myFileTools.get(file)) return null; - return new LocalInspectionsPass(file, editor.getDocument(), 0, file.getTextLength()) { + return new LocalInspectionsPass(file, editor.getDocument(), 0, file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true) { List getInspectionTools(InspectionProfileWrapper profile) { List tools = super.getInspectionTools(profile); List result = new ArrayList(); diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index 731cc9c3faf9..639610151560 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -537,7 +537,8 @@ public class GlobalInspectionContextImpl implements GlobalInspectionContext { final FileViewProvider viewProvider = psiManager.findViewProvider(virtualFile); final com.intellij.openapi.editor.Document document = viewProvider == null ? null : viewProvider.getDocument(); if (document == null || virtualFile.getFileType().isBinary()) return; //do not inspect binary files - final LocalInspectionsPass pass = new LocalInspectionsPass(file, document, 0, file.getTextLength()); + final LocalInspectionsPass pass = new LocalInspectionsPass(file, document, 0, + file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true); try { final List lTools = new ArrayList(); for (Tools tool : localTools) { @@ -546,7 +547,7 @@ public class GlobalInspectionContextImpl implements GlobalInspectionContext { lTools.add(enabledTool); } } - pass.doInspectInBatch((InspectionManagerEx)manager, lTools, true); + pass.doInspectInBatch((InspectionManagerEx)manager, lTools); } catch (ProcessCanceledException e) { throw e; diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/TransferToPooledThreadQueue.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/TransferToPooledThreadQueue.java new file mode 100644 index 000000000000..93cd04f40196 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/TransferToPooledThreadQueue.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2011 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.application.impl; + +import com.intellij.concurrency.JobScheduler; +import com.intellij.openapi.util.Condition; +import com.intellij.util.Processor; +import com.intellij.util.containers.TransferToEDTQueue; +import org.jetbrains.annotations.NotNull; + +/** + * Allows to process elements in the Application pooled thread. + * Processes elements in batches, no longer than 200ms per batch, and reschedules processing later for longer batches. + * Usage: {@link #offer(Object)} } : schedules element for processing in a pooled thread + */ +public class TransferToPooledThreadQueue extends TransferToEDTQueue { + + public TransferToPooledThreadQueue(@NotNull Processor processorInEDT, @NotNull Condition shutUpCondition) { + super(processorInEDT, shutUpCondition); + } + + @Override + protected void schedule(Runnable updateRunnable) { + JobScheduler.getScheduler().execute(updateRunnable); + //ApplicationManager.getApplication().executeOnPooledThread(updateRunnable); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java index efe9acd263ff..2eaa2ddab020 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java @@ -24,6 +24,7 @@ package com.intellij.openapi.vfs.encoding; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.impl.TransferToPooledThreadQueue; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; @@ -44,6 +45,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Alarm; +import com.intellij.util.Processor; import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -54,9 +56,7 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.nio.charset.Charset; import java.util.Collection; -import java.util.Queue; import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; @State( @@ -72,16 +72,14 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt private final Alarm updateEncodingFromContent = new Alarm(Alarm.ThreadToUse.OWN_THREAD, this); private static final Key CACHED_CHARSET_FROM_CONTENT = Key.create("CACHED_CHARSET_FROM_CONTENT"); - private final Queue myChangedDocuments = new ConcurrentLinkedQueue(); - private final Runnable myEncodingUpdateRunnable = new Runnable() { - public void run() { - for (int i=0; i<50;i++) { - if (!pollAndHandleDocument()) return; - } - // requeue myself to handle the tail of the queue in next request - addCacheEncodingAlarm(); + + private final TransferToPooledThreadQueue myChangedDocuments = new TransferToPooledThreadQueue(new Processor() { + @Override + public boolean process(Document document) { + handleDocument(document); + return true; } - }; + }, ApplicationManager.getApplication().getDisposed()); public EncodingManagerImpl(EditorFactory editorFactory) { editorFactory.getEventMulticaster().addDocumentListener(new DocumentAdapter() { @@ -99,9 +97,8 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt } @NonNls public static final String PROP_CACHED_ENCODING_CHANGED = "cachedEncoding"; - private boolean pollAndHandleDocument() { - final Document document = myChangedDocuments.poll(); - if (document == null) return false; + + private void handleDocument(final Document document) { ApplicationManager.getApplication().runReadAction(new Runnable(){ public void run() { VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document); @@ -114,28 +111,15 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt ((EncodingManagerImpl)EncodingManager.getInstance()).firePropertyChange(PROP_CACHED_ENCODING_CHANGED, oldCached, charset); } }); - return true; } public void dispose() { updateEncodingFromContent.cancelAllRequests(); - drainDocumentQueue(); - } - - public void drainDocumentQueue() { - while (pollAndHandleDocument()) { - // loop until empty - } + clearDocumentQueue(); } public void queueUpdateEncodingFromContent(@NotNull Document document) { myChangedDocuments.offer(document); - addCacheEncodingAlarm(); - } - - private void addCacheEncodingAlarm() { - updateEncodingFromContent.cancelAllRequests(); - updateEncodingFromContent.addRequest(myEncodingUpdateRunnable, 400); } public Charset getCachedCharsetFromContent(@NotNull Document document) { @@ -172,6 +156,10 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt return encodingManager.getEncoding(virtualFile, useParentDefaults); } + public void clearDocumentQueue() { + myChangedDocuments.stop(); + } + @Nullable private static Project guessProject(final VirtualFile virtualFile) { return ProjectLocator.getInstance().guessProjectForFile(virtualFile); diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index e301bf877394..cd1da081ce42 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -469,7 +469,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da } } EncodingManager encodingManager = EncodingManager.getInstance(); - if (encodingManager instanceof EncodingManagerImpl) ((EncodingManagerImpl)encodingManager).drainDocumentQueue(); + if (encodingManager instanceof EncodingManagerImpl) ((EncodingManagerImpl)encodingManager).clearDocumentQueue(); FileDocumentManager manager = FileDocumentManager.getInstance(); if (manager instanceof FileDocumentManagerImpl) { diff --git a/platform/usageView/testSrc/com/intellij/usages/impl/UsageViewMemoryTest.java b/platform/usageView/testSrc/com/intellij/usages/impl/UsageViewMemoryTest.java new file mode 100644 index 000000000000..7d56cc69b840 --- /dev/null +++ b/platform/usageView/testSrc/com/intellij/usages/impl/UsageViewMemoryTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2011 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.usages.impl; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vfs.encoding.EncodingManager; +import com.intellij.openapi.vfs.encoding.EncodingManagerImpl; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.testFramework.LeakHunter; +import com.intellij.testFramework.LightPlatformCodeInsightTestCase; +import com.intellij.usageView.UsageInfo; +import com.intellij.usages.*; +import com.intellij.util.ui.UIUtil; + +/** + * User: cdr + */ +public class UsageViewMemoryTest extends LightPlatformCodeInsightTestCase{ + public void testUsageViewDoesNotHoldPsiFilesOrDocuments() throws Exception { + PsiFile psiFile = createFile("X.java", "public class X{} //iuggjhfg"); + Usage[] usages = new Usage[100]; + for (int i = 0; i < usages.length; i++) { + usages[i] = createUsage(psiFile,i); + } + + UsageView usageView = UsageViewManager.getInstance(getProject()).createUsageView(UsageTarget.EMPTY_ARRAY, usages, new UsageViewPresentation(), null); + + Disposer.register(getTestRootDisposable(), usageView); + + UIUtil.dispatchAllInvocationEvents(); + ((EncodingManagerImpl)EncodingManager.getInstance()).clearDocumentQueue(); + + LeakHunter.checkLeak(usageView, PsiFileImpl.class); + LeakHunter.checkLeak(usageView, Document.class); + } + + private static Usage createUsage(PsiFile psiFile, int offset) { + PsiElement element = psiFile.findElementAt(offset % psiFile.getTextLength()); + assertNotNull(element); + return new UsageInfo2UsageAdapter(new UsageInfo(element)); + } +} diff --git a/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java b/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java index 4a241fe4550b..a03014ba0953 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java +++ b/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java @@ -151,7 +151,8 @@ public class DomUIFactoryImpl extends DomUIFactory { psiDocumentManager.commitAllDocuments(); GeneralHighlightingPass ghp = new GeneralHighlightingPass(project, psiFile, document, 0, document.getTextLength(), true); - LocalInspectionsPass lip = new LocalInspectionsPass(psiFile, document, 0, document.getTextLength()); + LocalInspectionsPass lip = new LocalInspectionsPass(psiFile, document, 0, + document.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true); return new HighlightingPass[]{ghp, lip}; }