From 7cd2d524a5879ae2c14accf73d1f0dc180dbdab0 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 12 Oct 2011 17:18:54 +0400 Subject: [PATCH] post highlighting: IDEA-73813 --- .../daemon/impl/PostHighlightingPass.java | 74 +++++++++---------- .../impl/PostHighlightingPassFactory.java | 29 ++++++-- .../daemon/DaemonAnalyzerTestCase.java | 26 ++++--- .../impl/JavaCodeInsightTestFixtureImpl.java | 8 -- .../WholeFileLocalInspectionsPassFactory.java | 16 +++- .../impl/CodeInsightTestFixtureImpl.java | 17 ++--- 6 files changed, 92 insertions(+), 78 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index 007595554526..ad0989d4912b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -95,7 +95,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { private Collection myHighlights; private boolean myHasRedundantImports; private final JavaCodeStyleManager myStyleManager; - private int myCurentEntryIndex; + private int myCurrentEntryIndex; private boolean myHasMissortedImports; private final ImplicitUsageProvider[] myImplicitUsageProviders; private UnusedDeclarationInspection myDeadCodeInspection; @@ -110,17 +110,15 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { PostHighlightingPass(@NotNull Project project, @NotNull PsiFile file, @Nullable Editor editor, - @NotNull Document document, - int startOffset, - int endOffset) { + @NotNull Document document) { super(project, document, true); myFile = file; myEditor = editor; - myStartOffset = startOffset; - myEndOffset = endOffset; + myStartOffset = 0; + myEndOffset = file.getTextLength(); myStyleManager = JavaCodeStyleManager.getInstance(myProject); - myCurentEntryIndex = -1; + myCurrentEntryIndex = -1; myImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME); } @@ -146,13 +144,10 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { myRefCountHolder = RefCountHolder.getInstance(myFile); if (!myRefCountHolder.retrieveUnusedReferencesInfo(new Runnable() { public void run() { - collectHighlights(elementSet, highlights, progress); + boolean errorFound = collectHighlights(elementSet, highlights, progress); myHighlights = highlights; - for (HighlightInfo info : highlights) { - if (info.getSeverity() == HighlightSeverity.ERROR) { - fileStatusMap.setErrorFoundFlag(myDocument, true); - break; - } + if (errorFound) { + fileStatusMap.setErrorFoundFlag(myDocument, true); } } })) { @@ -169,9 +164,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { public void doApplyInformationToEditor() { if (myHighlights == null) return; UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myHighlights, getColorsScheme(), Pass.POST_UPDATE_ALL); - - DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(myProject); - ((DaemonCodeAnalyzerImpl)daemonCodeAnalyzer).getFileStatusMap().markFileUpToDate(myDocument, myFile, getId()); + PostHighlightingPassFactory.markFileUpToDate(myFile); Editor editor = myEditor; if (editor != null && timeToOptimizeImports()) { @@ -212,7 +205,8 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { }); } - private void collectHighlights(@NotNull Collection elements, @NotNull final List result, @NotNull ProgressIndicator progress) throws ProcessCanceledException { + // returns true if error highlight was created + private boolean collectHighlights(@NotNull Collection elements, @NotNull final List result, @NotNull ProgressIndicator progress) throws ProcessCanceledException { ApplicationManager.getApplication().assertReadAccessAllowed(); InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); @@ -241,30 +235,36 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { myDeadCodeInfoType = myDeadCodeKey == null ? null : new HighlightInfoType.HighlightInfoTypeImpl(profile.getErrorLevel(myDeadCodeKey, myFile).getSeverity(), HighlightInfoType.UNUSED_SYMBOL.getAttributesKey()); - if (!unusedSymbolEnabled && !unusedImportEnabled) { - return; - } - for (PsiElement element : elements) { - progress.checkCanceled(); - - if (unusedSymbolEnabled && element instanceof PsiIdentifier) { - PsiIdentifier identifier = (PsiIdentifier)element; - HighlightInfo info = processIdentifier(identifier, progress); - if (info != null) { - result.add(info); - } - } - else if (unusedImportEnabled && element instanceof PsiImportList) { - final PsiImportStatementBase[] imports = ((PsiImportList)element).getAllImportStatements(); - for (PsiImportStatementBase statement : imports) { - progress.checkCanceled(); - final HighlightInfo info = processImport(statement, unusedImportKey); + boolean errorFound = false; + if (unusedSymbolEnabled) { + for (PsiElement element : elements) { + progress.checkCanceled(); + if (element instanceof PsiIdentifier) { + PsiIdentifier identifier = (PsiIdentifier)element; + HighlightInfo info = processIdentifier(identifier, progress); if (info != null) { + errorFound |= info.getSeverity() == HighlightSeverity.ERROR; result.add(info); } } } } + if (unusedImportEnabled && myFile instanceof PsiJavaFile) { + PsiImportList importList = ((PsiJavaFile)myFile).getImportList(); + if (importList != null) { + final PsiImportStatementBase[] imports = importList.getAllImportStatements(); + for (PsiImportStatementBase statement : imports) { + progress.checkCanceled(); + final HighlightInfo info = processImport(statement, unusedImportKey); + if (info != null) { + errorFound |= info.getSeverity() == HighlightSeverity.ERROR; + result.add(info); + } + } + } + } + + return errorFound; } @Nullable @@ -689,10 +689,10 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { } int entryIndex = myStyleManager.findEntryIndex(importStatement); - if (entryIndex < myCurentEntryIndex) { + if (entryIndex < myCurrentEntryIndex) { myHasMissortedImports = true; } - myCurentEntryIndex = entryIndex; + myCurrentEntryIndex = entryIndex; return null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java index 516c3646daa6..5dccca31de91 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java @@ -15,13 +15,18 @@ */ package com.intellij.codeInsight.daemon.impl; -import com.intellij.codeHighlighting.*; +import com.intellij.codeHighlighting.MainHighlightingPassFactory; +import com.intellij.codeHighlighting.Pass; +import com.intellij.codeHighlighting.TextEditorHighlightingPass; +import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar; import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiModificationTracker; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,6 +35,7 @@ import org.jetbrains.annotations.Nullable; * @author cdr */ public class PostHighlightingPassFactory extends AbstractProjectComponent implements MainHighlightingPassFactory { + private static final Key LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP"); public PostHighlightingPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar) { super(project); highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL,}, null, true, Pass.POST_UPDATE_ALL); @@ -44,17 +50,24 @@ public class PostHighlightingPassFactory extends AbstractProjectComponent implem @Nullable public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull final Editor editor) { TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.UPDATE_ALL); - if (textRange == null) return null; - int startOffset = 0; - int endOffset = editor.getDocument().getTextLength(); + if (textRange == null) { + Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP); + long currentStamp = PsiModificationTracker.SERVICE.getInstance(myProject).getModificationCount(); + if (lastStamp != null && lastStamp == currentStamp) { + return null; + } + } - return new PostHighlightingPass(myProject, file, editor, editor.getDocument(), startOffset, endOffset); + return new PostHighlightingPass(myProject, file, editor, editor.getDocument()); } @Override public TextEditorHighlightingPass createMainHighlightingPass(@NotNull PsiFile file, @NotNull Document document) { - int startOffset = 0; - int endOffset = document.getTextLength(); - return new PostHighlightingPass(myProject, file, null, document, startOffset, endOffset); + return new PostHighlightingPass(myProject, file, null, document); + } + + public static void markFileUpToDate(@NotNull PsiFile file) { + long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount(); + file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp); } } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java index 58c5ea04d482..c2cfb53f5d04 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java @@ -97,8 +97,7 @@ import java.util.List; import java.util.Map; public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { - private final Map myAvailableTools = new THashMap(); - private final Map myAvailableLocalTools = new THashMap(); + private final Map myAvailableTools = new THashMap(); private final FileTreeAccessFilter myFileTreeAccessFilter = new FileTreeAccessFilter(); @Override @@ -127,8 +126,13 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { @Override @NotNull public InspectionProfileEntry[] getInspectionTools(PsiElement element) { - final Collection tools = myAvailableLocalTools.values(); - return tools.toArray(new LocalInspectionToolWrapper[tools.size()]); + Collection values = myAvailableTools.values(); + List result = new ArrayList(); + for (InspectionProfileEntry value : values) { + InspectionTool tool = value instanceof InspectionTool ? (InspectionTool)value : new LocalInspectionToolWrapper((LocalInspectionTool)value); + result.add(tool); + } + return result.toArray(new InspectionTool[result.size()]); } @Override @@ -147,13 +151,14 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { @Override public HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key, PsiElement element) { - final LocalInspectionTool localInspectionTool = myAvailableTools.get(key.toString()); + final InspectionProfileEntry localInspectionTool = myAvailableTools.get(key.toString()); return localInspectionTool != null ? localInspectionTool.getDefaultLevel() : HighlightDisplayLevel.WARNING; } @Override public InspectionTool getInspectionTool(@NotNull String shortName, @NotNull PsiElement element) { - return myAvailableLocalTools.get(shortName); + InspectionProfileEntry entry = myAvailableTools.get(shortName); + return entry == null ? null : entry instanceof InspectionTool ? (InspectionTool)entry : new LocalInspectionToolWrapper((LocalInspectionTool)entry); } }; final InspectionProfileManager inspectionProfileManager = InspectionProfileManager.getInstance(); @@ -199,14 +204,14 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).assertPointersDisposed(); } - protected void enableInspectionTool(LocalInspectionTool tool){ + protected void enableInspectionTool(InspectionProfileEntry tool){ final String shortName = tool.getShortName(); final HighlightDisplayKey key = HighlightDisplayKey.find(shortName); - if (key == null){ - HighlightDisplayKey.register(shortName, tool.getDisplayName(), tool.getID()); + if (key == null) { + assert tool instanceof LocalInspectionTool; + HighlightDisplayKey.register(shortName, tool.getDisplayName(), ((LocalInspectionTool)tool).getID()); } myAvailableTools.put(shortName, tool); - myAvailableLocalTools.put(shortName, new LocalInspectionToolWrapper(tool)); } protected void enableInspectionToolsFromProvider(InspectionToolProvider toolProvider){ @@ -222,7 +227,6 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { protected void disableInspectionTool(String shortName){ myAvailableTools.remove(shortName); - myAvailableLocalTools.remove(shortName); } protected LocalInspectionTool[] configureLocalInspectionTools() { diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java index d6ae873272de..0cec239d533b 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java @@ -19,7 +19,6 @@ import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.search.ProjectScope; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture; @@ -64,13 +63,6 @@ public class JavaCodeInsightTestFixtureImpl extends CodeInsightTestFixtureImpl i return ((PsiJavaFile)psiFile).getClasses()[0]; } - @Override - protected PsiFile addFileToProject(String rootPath, String relativePath, String fileText) { - PsiFile file = super.addFileToProject(rootPath, relativePath, fileText); - ((PsiModificationTrackerImpl)PsiManager.getInstance(getProject()).getModificationTracker()).incCounter(); - return file; - } - @Override @NotNull public PsiClass findClass(@NotNull @NonNls final String name) { 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 85ddd9622960..c72fb71ccec5 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 @@ -22,11 +22,13 @@ import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory; import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar; import com.intellij.codeInsight.daemon.DaemonBundle; import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.ex.InspectionManagerEx; import com.intellij.codeInspection.ex.InspectionProfileWrapper; import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; import com.intellij.openapi.Disposable; import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.TextRange; @@ -59,6 +61,7 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone myProfileManager = profileManager; } + @Override @NonNls @NotNull public String getComponentName() { @@ -80,6 +83,7 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone }; myProfileManager.addProfilesListener(myProfilesListener); Disposer.register(myProject, new Disposable() { + @Override public void dispose() { myProfileManager.removeProfilesListener(myProfilesListener); myFileTools.clear(); @@ -87,6 +91,7 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone }); } + @Override @Nullable public TextEditorHighlightingPass createHighlightingPass(@NotNull final PsiFile file, @NotNull final Editor editor) { TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.LOCAL_INSPECTIONS); @@ -97,6 +102,7 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone } return new LocalInspectionsPass(file, editor.getDocument(), 0, file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true) { + @Override List getInspectionTools(InspectionProfileWrapper profile) { List tools = super.getInspectionTools(profile); List result = new ArrayList(tools.size()); @@ -112,8 +118,14 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone return DaemonBundle.message("pass.whole.inspections"); } - void inspectInjectedPsi(PsiElement[] elements, List tools) { - // inspected in LIP already + @Override + void inspectInjectedPsi(@NotNull List elements, + @NotNull List tools, + boolean onTheFly, + @NotNull ProgressIndicator indicator, + @NotNull InspectionManagerEx iManager, + boolean inVisibleRange) { + // already inspected in LIP } }; } diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index 0387301b6c19..8be55920ff8f 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -25,10 +25,7 @@ import com.intellij.codeInsight.completion.CompletionType; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings; import com.intellij.codeInsight.daemon.HighlightDisplayKey; -import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl; -import com.intellij.codeInsight.daemon.impl.HighlightInfo; -import com.intellij.codeInsight.daemon.impl.HighlightInfoType; -import com.intellij.codeInsight.daemon.impl.ShowIntentionsPass; +import com.intellij.codeInsight.daemon.impl.*; import com.intellij.codeInsight.folding.CodeFoldingManager; import com.intellij.codeInsight.highlighting.actions.HighlightUsagesAction; import com.intellij.codeInsight.intention.IntentionAction; @@ -50,7 +47,6 @@ import com.intellij.ide.startup.impl.StartupManagerImpl; import com.intellij.ide.structureView.StructureViewBuilder; import com.intellij.ide.structureView.newStructureView.StructureViewComponent; import com.intellij.lang.LanguageStructureViewBuilder; -import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionManagerEx; @@ -91,6 +87,7 @@ import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.impl.PsiManagerImpl; +import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.impl.cache.CacheManager; import com.intellij.psi.impl.cache.impl.todo.TodoIndex; import com.intellij.psi.impl.source.PostprocessReformattingAspect; @@ -153,7 +150,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig @NonNls private static final String XXX = "XXX"; private final FileTreeAccessFilter myJavaFilesFilter = new FileTreeAccessFilter(); private boolean myAllowDirt; - private boolean toInitializeDaemon; public CodeInsightTestFixtureImpl(IdeaProjectTestFixture projectFixture, TempDirTestFixture tempDirTestFixture) { myProjectFixture = projectFixture; @@ -810,7 +806,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig @Override @Nullable public GutterIconRenderer findGutter(final String filePath) { - assertInitialized(); configureByFilesInner(filePath); int offset = myEditor.getCaretModel().getOffset(); @@ -838,7 +833,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig @Override @NotNull public Collection findAllGutters(final String filePath) { - assertInitialized(); final Project project = getProject(); final SortedMap> result = new TreeMap>(); configureByFilesInner(filePath); @@ -885,6 +879,9 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig catch (IOException e) { throw new RuntimeException(e); } + finally { + ((PsiModificationTrackerImpl)PsiManager.getInstance(getProject()).getModificationTracker()).incCounter(); + } } public void registerExtension(final ExtensionsArea area, final ExtensionPointName epName, final T extension) { @@ -1060,9 +1057,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig for (VirtualFile openFile : openFiles) { editorManager.closeFile(openFile); } - if (toInitializeDaemon) { - ((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(!LightPlatformTestCase.isLight(getProject())); - } myEditor = null; myFile = null; @@ -1166,7 +1160,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig @Override public PsiFile configureByFile(final String file) { - assertInitialized(); configureByFilesInner(file); return myFile; }