diff options
Diffstat (limited to 'platform/lang-impl/src/com')
105 files changed, 1926 insertions, 1455 deletions
diff --git a/platform/lang-impl/src/com/intellij/application/options/CodeStyleSchemesConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/CodeStyleSchemesConfigurable.java index b07c7a62bc47..760d17e67d24 100644 --- a/platform/lang-impl/src/com/intellij/application/options/CodeStyleSchemesConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/CodeStyleSchemesConfigurable.java @@ -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. @@ -56,7 +56,7 @@ public class CodeStyleSchemesConfigurable extends SearchableConfigurable.Parent. public JComponent createComponent() { myModel = ensureModel(); - if (Registry.is("ide.file.settings.order.new")) { + if (Registry.is("ide.new.settings.dialog")) { return myPanels == null || myPanels.isEmpty() ? null : myPanels.get(0).createComponent(); } return myRootSchemesPanel.getPanel(); @@ -236,7 +236,7 @@ public class CodeStyleSchemesConfigurable extends SearchableConfigurable.Parent. } } - if (Registry.is("ide.file.settings.order.new")) { + if (Registry.is("ide.new.settings.dialog")) { int size = myPanels.size(); Configurable[] result = new Configurable[size > 0 ? size - 1 : 0]; for (int i = 0; i < result.length; i++) { @@ -346,34 +346,31 @@ public class CodeStyleSchemesConfigurable extends SearchableConfigurable.Parent. String displayName = myProvider.getConfigurableDisplayName(); if (displayName != null) return displayName; - return ensurePanel().getDisplayName(); // fallback for 8.0 API compatibility + return myPanel != null ? myPanel.getDisplayName() : null; // fallback for 8.0 API compatibility } @Override public String getHelpTopic() { - return ensurePanel().getHelpTopic(); - } - - private CodeStyleMainPanel ensurePanel() { - if (myPanel == null) { - myPanel = new CodeStyleMainPanel(ensureModel(), myLangSelector, myFactory); - } - return myPanel; + return myPanel != null ? myPanel.getHelpTopic() : null; } @Override public JComponent createComponent() { - return ensurePanel(); + myPanel = new CodeStyleMainPanel(ensureModel(), myLangSelector, myFactory); + return myPanel; } @Override public boolean isModified() { - boolean someSchemeModified = ensurePanel().isModified(); - if (someSchemeModified) { - myApplyCompleted = false; - myRevertCompleted = false; + if (myPanel != null) { + boolean someSchemeModified = myPanel.isModified(); + if (someSchemeModified) { + myApplyCompleted = false; + myRevertCompleted = false; + } + return someSchemeModified; } - return someSchemeModified; + return false; } @Override @@ -428,20 +425,25 @@ public class CodeStyleSchemesConfigurable extends SearchableConfigurable.Parent. } public boolean isPanelModified(CodeStyleScheme scheme) { - return ensurePanel().isModified(scheme); + return myPanel != null && myPanel.isModified(scheme); } public boolean isPanelModified() { - return ensurePanel().isModified(); + return myPanel != null && myPanel.isModified(); } public void applyPanel() throws ConfigurationException { - ensurePanel().apply(); + if (myPanel != null) { + myPanel.apply(); + } } @Override public Set<String> processListOptions() { - return ensurePanel().processListOptions(); + if (myPanel == null) { + myPanel = new CodeStyleMainPanel(ensureModel(), myLangSelector, myFactory); + } + return myPanel.processListOptions(); } } } diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form index 586f9b48779e..3ce71602fe06 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form @@ -259,7 +259,7 @@ <component id="25b75" class="javax.swing.JTextField" binding="myClipboardContentLimitTextField"> <constraints> <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="4" anchor="8" fill="0" indent="0" use-parent-layout="false"> - <preferred-size width="35" height="-1"/> + <preferred-size width="50" height="-1"/> </grid> </constraints> <properties> @@ -285,7 +285,7 @@ <component id="695ab" class="javax.swing.JTextField" binding="myRecentFilesLimitField"> <constraints> <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"> - <preferred-size width="35" height="-1"/> + <preferred-size width="50" height="-1"/> </grid> </constraints> <properties> @@ -295,7 +295,7 @@ <component id="8f324" class="javax.swing.JTextField" binding="myCommandsHistoryLimitField"> <constraints> <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"> - <preferred-size width="35" height="-1"/> + <preferred-size width="50" height="-1"/> </grid> </constraints> <properties> diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index 0bc36c17325d..3b51cc9ad976 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -20,6 +20,7 @@ import com.intellij.openapi.application.Result; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.impl.EditorFactoryImpl; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; @@ -281,7 +282,7 @@ public class FormatChangedTextUtil { @NotNull private static List<TextRange> calculateChangedTextRanges(@NotNull Project project, @NotNull PsiFile file, @NotNull String contentFromVcs) { - Document documentFromVcs = EditorFactory.getInstance().createDocument(contentFromVcs); + Document documentFromVcs = ((EditorFactoryImpl)EditorFactory.getInstance()).createDocument(contentFromVcs, true, false); Document document = PsiDocumentManager.getInstance(project).getDocument(file); if (document == null) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index ed254aec1e8b..6cdb063c0434 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -82,8 +82,9 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { public void run() { CodeStyleManagerImpl.setSequentialProcessingAllowed(false); try { - for (Runnable runnable : runnables) + for (Runnable runnable : runnables) { runnable.run(); + } } finally { CodeStyleManagerImpl.setSequentialProcessingAllowed(true); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index fcb080dcd277..3bdd05f58a40 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -316,7 +316,6 @@ public class CodeCompletionHandlerBase { final LookupElement[] allItems = data.get(); if (allItems != null && !indicator.isRunning() && !indicator.isCanceled()) { // the completion is really finished, now we may auto-insert or show lookup completionFinished(initContext.getStartOffset(), initContext.getSelectionEndOffset(), indicator, allItems, hasModifiers); - checkNotSync(indicator, allItems); return; } } @@ -424,18 +423,18 @@ public class CodeCompletionHandlerBase { LOG.assertTrue(!indicator.isRunning(), "running"); LOG.assertTrue(!indicator.isCanceled(), "canceled"); - indicator.getLookup().refreshUi(true, false); - final AutoCompletionDecision decision = shouldAutoComplete(indicator, items); - if (decision == AutoCompletionDecision.SHOW_LOOKUP) { - CompletionServiceImpl.setCompletionPhase(new CompletionPhase.ItemsCalculated(indicator)); - indicator.getLookup().setCalculating(false); - indicator.showLookup(); - } - else if (decision instanceof AutoCompletionDecision.InsertItem) { - final Runnable restorePrefix = rememberDocumentState(indicator.getEditor()); + try { + indicator.getLookup().refreshUi(true, false); + final AutoCompletionDecision decision = shouldAutoComplete(indicator, items); + if (decision == AutoCompletionDecision.SHOW_LOOKUP) { + CompletionServiceImpl.setCompletionPhase(new CompletionPhase.ItemsCalculated(indicator)); + indicator.getLookup().setCalculating(false); + indicator.showLookup(); + } + else if (decision instanceof AutoCompletionDecision.InsertItem) { + final Runnable restorePrefix = rememberDocumentState(indicator.getEditor()); - final LookupElement item = ((AutoCompletionDecision.InsertItem)decision).getElement(); - try { + final LookupElement item = ((AutoCompletionDecision.InsertItem)decision).getElement(); CommandProcessor.getInstance().executeCommand(indicator.getProject(), new Runnable() { @Override public void run() { @@ -443,22 +442,22 @@ public class CodeCompletionHandlerBase { indicator.getLookup().finishLookup(Lookup.AUTO_INSERT_SELECT_CHAR, item); } }, "Autocompletion", null); - } - catch (Throwable e) { - CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); - LOG.error(e); - return; - } - // the insert handler may have started a live template with completion - if (CompletionService.getCompletionService().getCurrentCompletion() == null && - // ...or scheduled another autopopup - !CompletionServiceImpl.isPhase(CompletionPhase.CommittingDocuments.class)) { - CompletionServiceImpl.setCompletionPhase(hasModifiers? new CompletionPhase.InsertedSingleItem(indicator, restorePrefix) : CompletionPhase.NoCompletion); + // the insert handler may have started a live template with completion + if (CompletionService.getCompletionService().getCurrentCompletion() == null && + // ...or scheduled another autopopup + !CompletionServiceImpl.isPhase(CompletionPhase.CommittingDocuments.class)) { + CompletionServiceImpl.setCompletionPhase(hasModifiers? new CompletionPhase.InsertedSingleItem(indicator, restorePrefix) : CompletionPhase.NoCompletion); + } + } else if (decision == AutoCompletionDecision.CLOSE_LOOKUP) { + LookupManager.getInstance(indicator.getProject()).hideActiveLookup(); } - checkNotSync(indicator, items); - } else if (decision == AutoCompletionDecision.CLOSE_LOOKUP) { - LookupManager.getInstance(indicator.getProject()).hideActiveLookup(); + } + catch (Throwable e) { + CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); + LOG.error(e); + } + finally { checkNotSync(indicator, items); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java index e25f050c8d7b..8ca94d80463c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -193,9 +193,10 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement if (!CodeInsightSettings.getInstance().SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS) { myLookup.setFocusDegree(LookupImpl.FocusDegree.SEMI_FOCUSED); if (FeatureUsageTracker.getInstance().isToBeAdvertisedInLookup(CodeCompletionFeatures.EDITING_COMPLETION_FINISH_BY_CONTROL_DOT, getProject())) { - addAdvertisement("Press " + - CompletionContributor.getActionShortcut(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_DOT) + - " to choose the selected (or first) suggestion and insert a dot afterwards", null); + String dotShortcut = CompletionContributor.getActionShortcut(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_DOT); + if (StringUtil.isNotEmpty(dotShortcut)) { + addAdvertisement("Press " + dotShortcut + " to choose the selected (or first) suggestion and insert a dot afterwards", null); + } } } else { myLookup.setFocusDegree(LookupImpl.FocusDegree.FOCUSED); @@ -204,9 +205,11 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement if (!myEditor.isOneLineMode() && FeatureUsageTracker.getInstance() .isToBeAdvertisedInLookup(CodeCompletionFeatures.EDITING_COMPLETION_CONTROL_ARROWS, getProject())) { - addAdvertisement(CompletionContributor.getActionShortcut(IdeActions.ACTION_LOOKUP_DOWN) + " and " + - CompletionContributor.getActionShortcut(IdeActions.ACTION_LOOKUP_UP) + - " will move caret down and up in the editor", null); + String downShortcut = CompletionContributor.getActionShortcut(IdeActions.ACTION_LOOKUP_DOWN); + String upShortcut = CompletionContributor.getActionShortcut(IdeActions.ACTION_LOOKUP_UP); + if (StringUtil.isNotEmpty(downShortcut) && StringUtil.isNotEmpty(upShortcut)) { + addAdvertisement(downShortcut + " and " + upShortcut + " will move caret down and up in the editor", null); + } } } else if (DumbService.isDumb(getProject())) { addAdvertisement("The results might be incomplete while indexing is in progress", MessageType.WARNING.getPopupBackground()); @@ -759,6 +762,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement data.set(calculateItems(initContext, weigher)); } catch (ProcessCanceledException ignore) { + cancel(); // some contributor may just throw PCE; if indicator is not canceled everything will hang } catch (Throwable t) { cancel(); 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 d8fd3ab40508..4ac5e686c5bc 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 @@ -709,11 +709,20 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements JDOM return new Runnable() { @Override public void run() { - if (myDisposed || !myProject.isInitialized()) return; - if (PowerSaveMode.isEnabled()) return; - Editor activeEditor = FileEditorManager.getInstance(myProject).getSelectedTextEditor(); + ApplicationManager.getApplication().assertIsDispatchThread(); + if (myDisposed || !myProject.isInitialized() || PowerSaveMode.isEnabled()) { + return; + } + if (HeavyProcessLatch.INSTANCE.isRunning()) { + if (myAlarm.isEmpty()) { + myAlarm.addRequest(myUpdateRunnable, mySettings.AUTOREPARSE_DELAY); + } + return; + } + Editor activeEditor = FileEditorManager.getInstance(myProject).getSelectedTextEditor(); final PsiDocumentManagerImpl documentManager = (PsiDocumentManagerImpl)PsiDocumentManager.getInstance(myProject); + Runnable runnable = new Runnable() { @Override public void run() { @@ -728,7 +737,6 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements JDOM final Collection<FileEditor> activeEditors = getSelectedEditors(); if (activeEditors.isEmpty()) return; - ApplicationManager.getApplication().assertIsDispatchThread(); if (ApplicationManager.getApplication().isWriteAccessAllowed()) { // makes no sense to start from within write action, will cancel anyway // we'll restart when write action finish diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java index c8d5ec4b8ddb..760029d689db 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java @@ -507,7 +507,7 @@ public class DaemonListeners implements Disposable { } @Override - public void profileActivated(@NotNull Profile oldProfile, Profile profile) { + public void profileActivated(Profile oldProfile, Profile profile) { stopDaemonAndRestartAllFiles(); } @@ -530,6 +530,7 @@ public class DaemonListeners implements Disposable { StatusBarEx statusBar = (StatusBarEx)WindowManager.getInstance().getStatusBar(myProject); myTogglePopupHintsPanel = new TogglePopupHintsPanel(myProject); statusBar.addWidget(myTogglePopupHintsPanel, myProject); + updateStatusBar(); stopDaemonAndRestartAllFiles(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/EditorTracker.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/EditorTracker.java index cfa7c029d8fc..c88ac636243a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/EditorTracker.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/EditorTracker.java @@ -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. @@ -209,7 +209,7 @@ public class EditorTracker extends AbstractProjectComponent { return filtered; } - private void setActiveEditors(@NotNull List<Editor> editors) { + void setActiveEditors(@NotNull List<Editor> editors) { myActiveEditors = editors; if (LOG.isDebugEnabled()) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java index 2c44451ef260..72b0a4471e9c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java @@ -34,6 +34,7 @@ import com.intellij.openapi.editor.markup.MarkupModel; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; @@ -115,33 +116,50 @@ public class IdentifierHighlighterPass extends TextEditorHighlightingPass { } } - private void highlightTargetUsages(@NotNull PsiElement target) { + /** + * Returns read and write usages of psi element inside single file + * + * @param target target psi element + * @param psiFile psi file for element + * @return a pair where first element is read usages and second is write usages + */ + public static Couple<Collection<TextRange>> getHighlightUsages(@NotNull PsiElement target, PsiFile psiFile) { + Collection<TextRange> readRanges = new ArrayList<TextRange>(); + Collection<TextRange> writeRanges = new ArrayList<TextRange>(); final ReadWriteAccessDetector detector = ReadWriteAccessDetector.findDetector(target); final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(target.getProject())).getFindUsagesManager(); final FindUsagesHandler findUsagesHandler = findUsagesManager.getFindUsagesHandler(target, true); - final LocalSearchScope scope = new LocalSearchScope(myFile); + final LocalSearchScope scope = new LocalSearchScope(psiFile); Collection<PsiReference> refs = findUsagesHandler != null ? findUsagesHandler.findReferencesToHighlight(target, scope) : ReferencesSearch.search(target, scope).findAll(); for (PsiReference psiReference : refs) { final List<TextRange> textRanges = HighlightUsagesHandler.getRangesToHighlight(psiReference); if (detector == null || detector.getReferenceAccess(target, psiReference) == ReadWriteAccessDetector.Access.Read) { - myReadAccessRanges.addAll(textRanges); + readRanges.addAll(textRanges); } else { - myWriteAccessRanges.addAll(textRanges); + writeRanges.addAll(textRanges); } } - final TextRange declRange = HighlightUsagesHandler.getNameIdentifierRange(myFile, target); + final TextRange declRange = HighlightUsagesHandler.getNameIdentifierRange(psiFile, target); if (declRange != null) { if (detector != null && detector.isDeclarationWriteAccess(target)) { - myWriteAccessRanges.add(declRange); + writeRanges.add(declRange); } else { - myReadAccessRanges.add(declRange); + readRanges.add(declRange); } } + + return Couple.of(readRanges, writeRanges); + } + + private void highlightTargetUsages(@NotNull PsiElement target) { + final Couple<Collection<TextRange>> usages = getHighlightUsages(target, myFile); + myReadAccessRanges.addAll(usages.first); + myWriteAccessRanges.addAll(usages.second); } @Override 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 207b66be6112..0761379652ac 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 @@ -223,7 +223,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass Divider.divideInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, inside, new ArrayList<ProperTextRange>(), outside, new ArrayList<ProperTextRange>(), true, FILE_FILTER); - MultiMap<LocalInspectionToolWrapper, String> toolToLanguages = getToolsForElements(toolWrappers, checkDumbAwareness, inside, outside); + MultiMap<LocalInspectionToolWrapper, String> toolToLanguages = InspectionEngine.getToolsForElements(toolWrappers, checkDumbAwareness, inside, outside); setProgressLimit(toolToLanguages.size() * 2L); final LocalInspectionToolSession session = new LocalInspectionToolSession(myFile, myStartOffset, myEndOffset); @@ -240,76 +240,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } @NotNull - private static MultiMap<LocalInspectionToolWrapper, String> getToolsForElements(@NotNull List<LocalInspectionToolWrapper> toolWrappers, - boolean checkDumbAwareness, - @NotNull List<PsiElement> inside, - @NotNull List<PsiElement> outside) { - Set<Language> languages = new SmartHashSet<Language>(); - Map<String, Language> langIds = new SmartHashMap<String, Language>(); - Set<String> dialects = new SmartHashSet<String>(); - calculateDialects(inside, languages, langIds, dialects); - calculateDialects(outside, languages, langIds, dialects); - MultiMap<LocalInspectionToolWrapper, String> toolToLanguages = new MultiMap<LocalInspectionToolWrapper, String>() { - @NotNull - @Override - protected Collection<String> createCollection() { - return new SmartHashSet<String>(); - } - - @NotNull - @Override - protected Collection<String> createEmptyCollection() { - return Collections.emptySet(); - } - }; - for (LocalInspectionToolWrapper wrapper : toolWrappers) { - ProgressManager.checkCanceled(); - String language = wrapper.getLanguage(); - if (language == null) { - LocalInspectionTool tool = wrapper.getTool(); - if (!checkDumbAwareness || tool instanceof DumbAware) { - toolToLanguages.put(wrapper, null); - } - continue; - } - Language lang = langIds.get(language); - if (lang != null) { - LocalInspectionTool tool = wrapper.getTool(); - if (!checkDumbAwareness || tool instanceof DumbAware) { - toolToLanguages.putValue(wrapper, language); - if (wrapper.applyToDialects()) { - for (Language dialect : lang.getDialects()) { - toolToLanguages.putValue(wrapper, dialect.getID()); - } - } - } - } - else if (wrapper.applyToDialects() && dialects.contains(language)) { - LocalInspectionTool tool = wrapper.getTool(); - if (!checkDumbAwareness || tool instanceof DumbAware) { - toolToLanguages.putValue(wrapper, language); - } - } - } - return toolToLanguages; - } - - private static void calculateDialects(@NotNull List<PsiElement> inside, - @NotNull Set<Language> languages, - @NotNull Map<String, Language> langIds, - @NotNull Set<String> dialects) { - for (PsiElement element : inside) { - Language language = element.getLanguage(); - if (languages.add(language)) { - langIds.put(language.getID(), language); - for (Language dialect : language.getDialects()) { - dialects.add(dialect.getID()); - } - } - } - } - - @NotNull private List<InspectionContext> visitPriorityElementsAndInit(@NotNull MultiMap<LocalInspectionToolWrapper, String> toolToLanguages, @NotNull final InspectionManagerEx iManager, final boolean isOnTheFly, @@ -412,17 +342,16 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass }); } if (injected.isEmpty()) return; - if (!JobLauncher.getInstance().invokeConcurrentlyUnderProgress(new ArrayList<PsiFile>(injected), indicator, - myFailFastOnAcquireReadAction, - new Processor<PsiFile>() { - @Override - public boolean process(final PsiFile injectedPsi) { - doInspectInjectedPsi(injectedPsi, onTheFly, indicator, iManager, - inVisibleRange, - wrappers, checkDumbAwareness); - return true; - } - })) throw new ProcessCanceledException(); + Processor<PsiFile> processor = new Processor<PsiFile>() { + @Override + public boolean process(final PsiFile injectedPsi) { + doInspectInjectedPsi(injectedPsi, onTheFly, indicator, iManager, inVisibleRange, wrappers, checkDumbAwareness); + return true; + } + }; + if (!JobLauncher.getInstance().invokeConcurrentlyUnderProgress(new ArrayList<PsiFile>(injected), indicator, myFailFastOnAcquireReadAction, processor)) { + throw new ProcessCanceledException(); + } } @Nullable @@ -740,7 +669,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass return; } MultiMap<LocalInspectionToolWrapper, String> toolToLanguages = - getToolsForElements(wrappers, checkDumbAwareness, elements, Collections.<PsiElement>emptyList()); + InspectionEngine.getToolsForElements(wrappers, checkDumbAwareness, elements, Collections.<PsiElement>emptyList()); for (final Map.Entry<LocalInspectionToolWrapper, Collection<String>> pair : toolToLanguages.entrySet()) { indicator.checkCanceled(); final LocalInspectionToolWrapper wrapper = pair.getKey(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java index 1f47f5c5c69a..57f65283fd2f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java @@ -33,6 +33,7 @@ import com.intellij.ui.CollectionListModel; import com.intellij.ui.JBListWithHintProvider; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.popup.AbstractPopup; +import com.intellij.ui.popup.HintUpdateSupply; import com.intellij.usages.UsageView; import com.intellij.util.Consumer; import com.intellij.util.Processor; @@ -147,8 +148,7 @@ public class PsiElementListNavigator { setCancelCallback(new Computable<Boolean>() { @Override public Boolean compute() { - list.hideHint(); - + HintUpdateSupply.hideHint(list); return true; } }); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SmartHashMap.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SmartHashMap.java deleted file mode 100644 index 861df82d5d43..000000000000 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SmartHashMap.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2000-2013 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.codeInsight.daemon.impl; - -import com.intellij.openapi.util.Comparing; -import com.intellij.util.IncorrectOperationException; -import com.intellij.util.SingletonSet; -import gnu.trove.THashMap; -import gnu.trove.TObjectFunction; -import gnu.trove.TObjectObjectProcedure; -import gnu.trove.TObjectProcedure; -import org.jetbrains.annotations.NotNull; - -import java.util.AbstractMap; -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -/** - * Hash set (based on THashSet) which is fast when contains one or zero elements (avoids to calculate hash codes and call equals whenever possible). - * For other sizes it delegates to THashSet. - * Null keys are NOT PERMITTED. - */ -public class SmartHashMap<K,V> extends THashMap<K,V> { - private K theKey; // contains the only element if size() == 1 - private V theValue; - - @Override - public boolean containsKey(@NotNull Object key) { - K theKey = this.theKey; - if (theKey != null) { - return eq(theKey, (K)key); - } - return !super.isEmpty() && super.containsKey(key); - } - - @Override - public V put(@NotNull K key, V value) { - K theKey = this.theKey; - if (theKey != null) { - if (eq(theKey, key)) return theValue; - super.put(theKey, theValue); - this.theKey = null; - // fallthrough - } - else if (super.isEmpty()) { - this.theKey = key; - theValue = value; - return null; - } - return super.put(key, value); - } - - private boolean eq(K obj, K theKey) { - return theKey == obj || _hashingStrategy.equals(theKey, obj); - } - - @Override - public boolean equals(@NotNull Object other) { - K theKey = this.theKey; - if (theKey != null) { - if (!(other instanceof Map) || ((Map)other).size() != 1 ) return false; - Map.Entry<K, V> entry = ((Map<K, V>)other).entrySet().iterator().next(); - return eq(theKey, entry.getKey()) && Comparing.equal(theValue, entry.getValue()); - } - - return super.equals(other); - } - - @Override - public int hashCode() { - K theKey = this.theKey; - if (theKey != null) { - return _hashingStrategy.computeHashCode(theKey); - } - return super.hashCode(); - } - - @Override - public void clear() { - theKey = null; - theValue = null; - super.clear(); - } - - @Override - public int size() { - K theKey = this.theKey; - if (theKey != null) { - return 1; - } - return super.size(); - } - - @Override - public boolean isEmpty() { - K theKey = this.theKey; - return theKey == null && super.isEmpty(); - } - - @Override - public V remove(@NotNull Object obj) { - K theKey = this.theKey; - if (theKey != null) { - if (eq(theKey, (K)obj)) { - this.theKey = null; - V value = theValue; - theValue = null; - return value; - } - return null; - } - return super.remove(obj); - } - - @NotNull - @Override - public Set<K> keySet() { - K theKey = this.theKey; - if (theKey != null) { - return new SingletonSet<K>(theKey); - } - return super.keySet(); - } - - @NotNull - @Override - public Collection<V> values() { - K theKey = this.theKey; - if (theKey != null) { - return new SingletonSet<V>(theValue); - } - return super.values(); - } - - @NotNull - @Override - public Set<Map.Entry<K, V>> entrySet() { - K theKey = this.theKey; - if (theKey != null) { - return new SingletonSet<Map.Entry<K, V>>(new AbstractMap.SimpleEntry<K, V>(theKey, theValue)); - } - return super.entrySet(); - } - - @Override - public V get(Object key) { - K theKey = this.theKey; - if (theKey != null) { - return eq(theKey, (K)key) ? theValue : null; - } - return super.get(key); - } - - @Override - public boolean containsValue(Object val) { - K theKey = this.theKey; - if (theKey != null) { - return Comparing.equal(theValue, val); - } - return super.containsValue(val); - } - - @Override - public THashMap<K, V> clone() { - throw new IncorrectOperationException(); - } - - @Override - public void transformValues(TObjectFunction<V, V> function) { - throw new IncorrectOperationException(); - } - - @Override - public boolean retainEntries(TObjectObjectProcedure<K, V> procedure) { - throw new IncorrectOperationException(); - } - - @Override - public boolean forEachEntry(TObjectObjectProcedure<K, V> procedure) { - throw new IncorrectOperationException(); - } - - @Override - public boolean forEachValue(TObjectProcedure<V> procedure) { - throw new IncorrectOperationException(); - } - - @Override - public boolean forEachKey(TObjectProcedure<K> procedure) { - throw new IncorrectOperationException(); - } -} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java index 9c4404a21d58..c67af24d8cdc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -42,7 +42,6 @@ import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiFile; import com.intellij.ui.LayeredIcon; import com.intellij.util.ArrayUtil; -import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.UIUtil; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NonNls; @@ -57,9 +56,7 @@ import java.util.List; import java.util.Set; public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { - private static final Icon IN_PROGRESS_ICON = AllIcons.General.ErrorsInProgress; private static final Icon NO_ANALYSIS_ICON = AllIcons.General.NoAnalysis; - private static final Icon NO_ICON = new EmptyIcon(IN_PROGRESS_ICON.getIconWidth(), IN_PROGRESS_ICON.getIconHeight()); private static final Icon STARING_EYE_ICON = AllIcons.General.InspectionInProgress; private final Project myProject; @@ -162,6 +159,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { public boolean enabled = true; public int rootsNumber; + @Override public String toString() { @NonNls String s = "DS: finished=" + errorAnalyzingFinished; s += "; pass statuses: " + passStati.size() + "; "; @@ -175,7 +173,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { @Nullable protected DaemonCodeAnalyzerStatus getDaemonCodeAnalyzerStatus(boolean fillErrorsCount, SeverityRegistrar severityRegistrar) { - if (myFile == null || myProject.isDisposed() || !myDaemonCodeAnalyzer.isHighlightingAvailable(myFile)) return null; + if (myFile == null || myProject != null && myProject.isDisposed() || !myDaemonCodeAnalyzer.isHighlightingAvailable(myFile)) return null; List<String> noInspectionRoots = new ArrayList<String>(); List<String> noHighlightingRoots = new ArrayList<String>(); @@ -243,10 +241,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { } private Icon getIcon(DaemonCodeAnalyzerStatus status) { - if (status == null) { - return NO_ICON; - } - if (status.noHighlightingRoots != null && status.noHighlightingRoots.length == status.rootsNumber) { + if (status == null || status.noHighlightingRoots != null && status.noHighlightingRoots.length == status.rootsNumber) { return NO_ANALYSIS_ICON; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java index 19a958a8bd71..74cfdd9f434e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java @@ -137,31 +137,33 @@ public class TrafficProgressPanel extends JPanel { } } - private void rebuildPassesPanel(@NotNull TrafficLightRenderer.DaemonCodeAnalyzerStatus status) { + private void rebuildPassesPanel(@Nullable TrafficLightRenderer.DaemonCodeAnalyzerStatus status) { myPassStatuses.removeAll(); myPassStatuses.setLayout(new GridBagLayout()); passes.clear(); GridBagConstraints c = new GridBagConstraints(); c.gridy = 0; c.fill = GridBagConstraints.HORIZONTAL; - for (ProgressableTextEditorHighlightingPass pass : status.passStati) { - JLabel label = new JLabel(pass.getPresentableName() + ": "); - label.setHorizontalTextPosition(SwingConstants.RIGHT); + if (status != null) { + for (ProgressableTextEditorHighlightingPass pass : status.passStati) { + JLabel label = new JLabel(pass.getPresentableName() + ": "); + label.setHorizontalTextPosition(SwingConstants.RIGHT); - JProgressBar progressBar = new JProgressBar(0, MAX); - progressBar.putClientProperty("JComponent.sizeVariant", "mini"); - JLabel percLabel = new JLabel(); - passes.put(pass, Pair.create(progressBar, percLabel)); - myProgressToText.put(progressBar, percLabel); - c.gridx = 0; - myPassStatuses.add(label, c); - c.gridx = 1; - myPassStatuses.add(progressBar, c); - c.gridx = 2; - c.weightx = 1; - myPassStatuses.add(percLabel, c); + JProgressBar progressBar = new JProgressBar(0, MAX); + progressBar.putClientProperty("JComponent.sizeVariant", "mini"); + JLabel percLabel = new JLabel(); + passes.put(pass, Pair.create(progressBar, percLabel)); + myProgressToText.put(progressBar, percLabel); + c.gridx = 0; + myPassStatuses.add(label, c); + c.gridx = 1; + myPassStatuses.add(progressBar, c); + c.gridx = 2; + c.weightx = 1; + myPassStatuses.add(percLabel, c); - c.gridy++; + c.gridy++; + } } myHintHint.initStyle(myPassStatuses, true); @@ -169,7 +171,6 @@ public class TrafficProgressPanel extends JPanel { } public void updatePanel(@Nullable TrafficLightRenderer.DaemonCodeAnalyzerStatus status, boolean isFake) { - if (status == null) return; boolean isDumb = DumbService.isDumb(myTrafficLightRenderer.getProject()); dumbLabel.setVisible(isDumb); try { @@ -178,6 +179,12 @@ public class TrafficProgressPanel extends JPanel { myPassStatuses.setVisible(false); statistics.setText(""); } + else if (status == null || status.noHighlightingRoots != null && status.noHighlightingRoots.length == status.rootsNumber) { + statusLabel.setText(DaemonBundle.message("analysis.hasnot.been.run")); + myPassStatuses.setVisible(true); + setPassesEnabled(false, Boolean.FALSE); + statistics.setText(""); + } else if (status.errorAnalyzingFinished) { if (isDumb) { statusLabel.setText("Shallow analysis completed"); @@ -194,12 +201,6 @@ public class TrafficProgressPanel extends JPanel { setPassesEnabled(false, Boolean.FALSE); statistics.setText(""); } - else if (status.noHighlightingRoots != null && status.noHighlightingRoots.length == status.rootsNumber) { - statusLabel.setText(DaemonBundle.message("analysis.hasnot.been.run")); - myPassStatuses.setVisible(true); - setPassesEnabled(false, Boolean.FALSE); - statistics.setText(""); - } else { statusLabel.setText(DaemonBundle.message("performing.code.analysis")); myPassStatuses.setVisible(true); @@ -207,42 +208,45 @@ public class TrafficProgressPanel extends JPanel { } - if (!status.passStati.equals(new ArrayList<ProgressableTextEditorHighlightingPass>(passes.keySet()))) { + if (status == null || + !status.passStati.equals(new ArrayList<ProgressableTextEditorHighlightingPass>(passes.keySet()))) { // passes set has changed rebuildPassesPanel(status); } - for (ProgressableTextEditorHighlightingPass pass : status.passStati) { - double progress = pass.getProgress(); - Pair<JProgressBar, JLabel> pair = passes.get(pass); - JProgressBar progressBar = pair.first; - int percent = (int)Math.round(progress * MAX); - progressBar.setValue(percent); - JLabel percentage = pair.second; - percentage.setText(percent + "%"); - } + if (status != null) { + for (ProgressableTextEditorHighlightingPass pass : status.passStati) { + double progress = pass.getProgress(); + Pair<JProgressBar, JLabel> pair = passes.get(pass); + JProgressBar progressBar = pair.first; + int percent = (int)Math.round(progress * MAX); + progressBar.setValue(percent); + JLabel percentage = pair.second; + percentage.setText(percent + "%"); + } - int currentSeverityErrors = 0; - @Language("HTML") - String text = ""; - for (int i = status.errorCount.length - 1; i >= 0; i--) { - if (status.errorCount[i] > 0) { - final HighlightSeverity severity = SeverityRegistrar.getSeverityRegistrar(myTrafficLightRenderer.getProject()).getSeverityByIndex(i); - String name = - status.errorCount[i] > 1 ? StringUtil.pluralize(severity.getName().toLowerCase()) : severity.getName().toLowerCase(); + int currentSeverityErrors = 0; + @Language("HTML") + String text = ""; + for (int i = status.errorCount.length - 1; i >= 0; i--) { + if (status.errorCount[i] > 0) { + final HighlightSeverity severity = SeverityRegistrar.getSeverityRegistrar(myTrafficLightRenderer.getProject()).getSeverityByIndex(i); + String name = + status.errorCount[i] > 1 ? StringUtil.pluralize(severity.getName().toLowerCase()) : severity.getName().toLowerCase(); + text += status.errorAnalyzingFinished + ? DaemonBundle.message("errors.found", status.errorCount[i], name) + : DaemonBundle.message("errors.found.so.far", status.errorCount[i], name); + text += "<br>"; + currentSeverityErrors += status.errorCount[i]; + } + } + if (currentSeverityErrors == 0) { text += status.errorAnalyzingFinished - ? DaemonBundle.message("errors.found", status.errorCount[i], name) - : DaemonBundle.message("errors.found.so.far", status.errorCount[i], name); - text += "<br>"; - currentSeverityErrors += status.errorCount[i]; + ? DaemonBundle.message("no.errors.or.warnings.found") + : DaemonBundle.message("no.errors.or.warnings.found.so.far") + "<br>"; } + statistics.setText(XmlStringUtil.wrapInHtml(text)); } - if (currentSeverityErrors == 0) { - text += status.errorAnalyzingFinished - ? DaemonBundle.message("no.errors.or.warnings.found") - : DaemonBundle.message("no.errors.or.warnings.found.so.far") + "<br>"; - } - statistics.setText(XmlStringUtil.wrapInHtml(text)); } finally { if (isFake) { 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 40a798c6af48..a1d95d51d7b4 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 @@ -76,7 +76,7 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone } @Override - public void profileActivated(@NotNull Profile oldProfile, Profile profile) { + public void profileActivated(Profile oldProfile, Profile profile) { myFileTools.clear(); } }; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java index 83f17299987b..e0d17d3c164b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java @@ -23,7 +23,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.AsyncResult; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowType; @@ -34,6 +34,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.ui.content.*; +import com.intellij.util.Consumer; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.Activatable; import com.intellij.util.ui.update.UiNotifyConnector; @@ -136,30 +137,33 @@ public abstract class DockablePopupManager<T extends JComponent & Disposable> { protected AnAction[] createActions() { - return new AnAction[]{ - new ToggleAction(getAutoUpdateTitle(), getAutoUpdateDescription(), - AllIcons.General.AutoscrollFromSource) { - @Override - public boolean isSelected(AnActionEvent e) { - return myAutoUpdateDocumentation; - } - - @Override - public void setSelected(AnActionEvent e, boolean state) { - PropertiesComponent.getInstance().setValue(getAutoUpdateEnabledProperty(), String.valueOf(state)); - myAutoUpdateDocumentation = state; - restartAutoUpdate(state); - } - }, - new AnAction("Restore Popup", getRestorePopupDescription(), AllIcons.Actions.Cancel) { - @Override - public void actionPerformed(AnActionEvent e) { - restorePopupBehavior(); - } - }}; + ToggleAction toggleAutoUpdateAction = new ToggleAction(getAutoUpdateTitle(), getAutoUpdateDescription(), + AllIcons.General.AutoscrollFromSource) { + @Override + public boolean isSelected(AnActionEvent e) { + return myAutoUpdateDocumentation; + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + PropertiesComponent.getInstance().setValue(getAutoUpdateEnabledProperty(), String.valueOf(state)); + myAutoUpdateDocumentation = state; + restartAutoUpdate(state); + } + }; + return new AnAction[]{toggleAutoUpdateAction, createRestorePopupAction()}; + } + + @NotNull + protected AnAction createRestorePopupAction() { + return new AnAction("Restore Popup", getRestorePopupDescription(), AllIcons.Actions.Cancel) { + @Override + public void actionPerformed(AnActionEvent e) { + restorePopupBehavior(); + } + }; } - protected void restartAutoUpdate(final boolean state) { if (state && myToolWindow != null) { if (myAutoUpdateRequest == null) { @@ -189,12 +193,16 @@ public abstract class DockablePopupManager<T extends JComponent & Disposable> { public void updateComponent() { if (myProject.isDisposed()) return; - AsyncResult<DataContext> asyncResult = DataManager.getInstance().getDataContextFromFocus(); - DataContext dataContext = asyncResult.getResult(); - if (dataContext == null) { - return; - } + DataManager.getInstance().getDataContextFromFocus().doWhenDone(new Consumer<DataContext>() { + @Override + public void consume(@NotNull DataContext dataContext) { + if (!myProject.isOpen()) return; + updateComponentInner(dataContext); + } + }); + } + private void updateComponentInner(@NotNull DataContext dataContext) { if (CommonDataKeys.PROJECT.getData(dataContext) != myProject) { return; } @@ -228,13 +236,10 @@ public abstract class DockablePopupManager<T extends JComponent & Disposable> { protected void restorePopupBehavior() { if (myToolWindow != null) { PropertiesComponent.getInstance().setValue(getShowInToolWindowProperty(), Boolean.FALSE.toString()); - - final Content[] contents = myToolWindow.getContentManager().getContents(); - for (final Content content : contents) { - myToolWindow.getContentManager().removeContent(content, true); - } - - ToolWindowManagerEx.getInstanceEx(myProject).unregisterToolWindow(getToolwindowId()); + ToolWindowManagerEx toolWindowManagerEx = ToolWindowManagerEx.getInstanceEx(myProject); + toolWindowManagerEx.hideToolWindow(getToolwindowId(), false); + toolWindowManagerEx.unregisterToolWindow(getToolwindowId()); + Disposer.dispose(myToolWindow.getContentManager()); myToolWindow = null; restartAutoUpdate(false); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index cf9b5ad22798..50f69088033b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -32,6 +32,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.ActionButton; import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; @@ -47,6 +48,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.SmartPointerManager; import com.intellij.psi.SmartPsiElementPointer; import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.JBColor; import com.intellij.ui.SideBorder; import com.intellij.ui.components.JBLayeredPane; import com.intellij.ui.components.JBScrollPane; @@ -66,10 +68,9 @@ import javax.swing.event.HyperlinkListener; import javax.swing.text.*; import java.awt.*; import java.awt.event.*; -import java.util.Collections; +import java.net.URL; +import java.util.*; import java.util.List; -import java.util.Map; -import java.util.Stack; public class DocumentationComponent extends JPanel implements Disposable, DataProvider { @@ -92,7 +93,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr private final Stack<Context> myBackStack = new Stack<Context>(); private final Stack<Context> myForwardStack = new Stack<Context>(); private final ActionToolbar myToolBar; - private boolean myIsEmpty; + private volatile boolean myIsEmpty; private boolean myIsShown; private final JLabel myElementLabel; private Style myFontSizeStyle; @@ -101,6 +102,13 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr private final MyShowSettingsButton myShowSettingsButton; private boolean myIgnoreFontSizeSliderChange; private String myEffectiveExternalUrl; + private final MyDictionary<String, Image> myImageProvider = new MyDictionary<String, Image>() { + @Override + public Image get(Object key) { + PsiElement element = getElement(); + return element == null ? null : myManager.getElementImage(element, ((URL)key).toExternalForm()); + } + }; private static class Context { final SmartPsiElementPointer element; @@ -178,6 +186,14 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr GraphicsUtil.setupAntialiasing(g); super.paintComponent(g); } + + @Override + public void setDocument(Document doc) { + super.setDocument(doc); + if (doc instanceof StyledDocument) { + doc.putProperty("imageCache", myImageProvider); + } + } }; DataProvider helpDataProvider = new DataProvider() { @Override @@ -308,6 +324,10 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr if (additionalActions != null) { for (final AnAction action : additionalActions) { actions.add(action); + ShortcutSet shortcutSet = action.getShortcutSet(); + if (shortcutSet != null) { + action.registerCustomShortcutSet(shortcutSet, this); + } } } @@ -378,7 +398,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr myFontSizeSlider.setSnapToTicks(true); UIUtil.setSliderIsFilled(myFontSizeSlider, true); result.add(myFontSizeSlider); - result.setBorder(BorderFactory.createLineBorder(UIUtil.getBorderColor(), 1)); + result.setBorder(BorderFactory.createLineBorder(JBColor.border(), 1)); myFontSizeSlider.addChangeListener(new ChangeListener() { @Override @@ -418,11 +438,11 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr } } - public synchronized boolean isEmpty() { + public boolean isEmpty() { return myIsEmpty; } - public synchronized void startWait() { + public void startWait() { myIsEmpty = true; } @@ -473,7 +493,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr } public void replaceText(String text, PsiElement element) { - if (element == null || getElement() != element) return; + PsiElement current = getElement(); + if (current == null || !current.getManager().areElementsEquivalent(current, element)) return; setText(text, element, false); if (!myBackStack.empty()) myBackStack.pop(); } @@ -530,6 +551,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr myText = text; } + //noinspection SSBasedInspection SwingUtilities.invokeLater(new Runnable() { @Override public void run() { @@ -544,7 +566,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr return; } - StyledDocument styledDocument = (StyledDocument)document; + final StyledDocument styledDocument = (StyledDocument)document; if (myFontSizeStyle == null) { myFontSizeStyle = styledDocument.addStyle("active", null); } @@ -555,7 +577,14 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr if (Registry.is("documentation.component.editor.font")) { StyleConstants.setFontFamily(myFontSizeStyle, scheme.getEditorFontName()); } - styledDocument.setCharacterAttributes(0, document.getLength(), myFontSizeStyle, false); + + final Style sizeStyle = myFontSizeStyle; + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + styledDocument.setCharacterAttributes(0, styledDocument.getLength(), sizeStyle, false); + } + }); } private void goBack() { @@ -631,15 +660,10 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr private class EditDocumentationSourceAction extends BaseNavigateToSourceAction { - protected EditDocumentationSourceAction() { + EditDocumentationSourceAction() { super(true); - } - - @Override - public void update(AnActionEvent event) { - super.update(event); - event.getPresentation().setIcon(AllIcons.Actions.EditSource); - event.getPresentation().setText("Edit Source"); + getTemplatePresentation().setIcon(AllIcons.Actions.EditSource); + getTemplatePresentation().setText("Edit Source"); } @Override @@ -678,8 +702,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr final PsiElement originalElement = DocumentationManager.getOriginalElement(element); boolean processed = false; if (provider instanceof CompositeDocumentationProvider) { - for (final DocumentationProvider documentationProvider : ((CompositeDocumentationProvider)provider).getProviders()) { - if (documentationProvider instanceof ExternalDocumentationHandler && ((ExternalDocumentationHandler)documentationProvider).handleExternal(element, originalElement)) { + for (DocumentationProvider p : ((CompositeDocumentationProvider)provider).getAllProviders()) { + if (p instanceof ExternalDocumentationHandler && ((ExternalDocumentationHandler)p).handleExternal(element, originalElement)) { processed = true; break; } @@ -874,4 +898,36 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr mySettingsPanel.setVisible(true); } } + + private static abstract class MyDictionary<K, V> extends Dictionary<K, V> { + @Override + public int size() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isEmpty() { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration<K> keys() { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration<V> elements() { + throw new UnsupportedOperationException(); + } + + @Override + public V put(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public V remove(Object key) { + throw new UnsupportedOperationException(); + } + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 05a1e01c6aa1..63484f890225 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -36,9 +36,11 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.actionSystem.ex.AnActionListener; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.OrderEntry; @@ -58,13 +60,13 @@ import com.intellij.psi.util.PsiUtilCore; import com.intellij.ui.ListScrollingUtil; import com.intellij.ui.content.Content; import com.intellij.ui.popup.AbstractPopup; -import com.intellij.ui.popup.NotLookupOrSearchCondition; import com.intellij.ui.popup.PopupPositionManager; import com.intellij.ui.popup.PopupUpdateProcessor; import com.intellij.util.Alarm; import com.intellij.util.BooleanFunction; import com.intellij.util.Consumer; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -125,6 +127,24 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp return "Auto Show Documentation for Selected Element"; } + @NotNull + @Override + protected AnAction createRestorePopupAction() { + AnAction restorePopupAction = super.createRestorePopupAction(); + ShortcutSet quickDocShortcut = ActionManager.getInstance().getAction(IdeActions.ACTION_QUICK_JAVADOC).getShortcutSet(); + restorePopupAction.registerCustomShortcutSet(quickDocShortcut, null); + return restorePopupAction; + } + + @Override + protected void restorePopupBehavior() { + if (myPreviouslyFocused != null) { + IdeFocusManager.getInstance(myProject).requestFocus(myPreviouslyFocused, true); + } + super.restorePopupBehavior(); + updateComponent(); + } + /** * @return <code>true</code> if quick doc control is configured to not prevent user-IDE interaction (e.g. should be closed if * the user presses a key); @@ -165,7 +185,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp @Override public void beforeEditorTyping(char c, DataContext dataContext) { final JBPopup hint = getDocInfoHint(); - if (hint != null) { + if (hint != null && LookupManager.getActiveLookup(myEditor) == null) { hint.cancel(); } } @@ -213,7 +233,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp } public void showJavaDocInfo(@NotNull final PsiElement element, final PsiElement original) { - showJavaDocInfo(element, original, false, null); + showJavaDocInfo(element, original, null); } /** @@ -229,35 +249,31 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp * two possible situations - the quick doc is shown automatically on mouse over element; the quick doc is shown * on explicit action call (Ctrl+Q). We want to close the doc on, say, editor viewport position change * at the first situation but don't want to do that at the second - * @param allowReuse defines whether currently requested documentation should reuse existing doc control (if any) */ public void showJavaDocInfo(@NotNull Editor editor, @NotNull final PsiElement element, @NotNull final PsiElement original, @Nullable Runnable closeCallback, - boolean closeOnSneeze, - boolean allowReuse) + boolean closeOnSneeze) { myEditor = editor; myCloseOnSneeze = closeOnSneeze; - showJavaDocInfo(element, original, allowReuse, closeCallback); + showJavaDocInfo(element, original, closeCallback); } public void showJavaDocInfo(@NotNull final PsiElement element, final PsiElement original, - boolean allowReuse, - @Nullable Runnable closeCallback) - { + @Nullable Runnable closeCallback) { PopupUpdateProcessor updateProcessor = new PopupUpdateProcessor(element.getProject()) { @Override public void updatePopup(Object lookupItemObject) { if (lookupItemObject instanceof PsiElement) { - doShowJavaDocInfo((PsiElement)lookupItemObject, false, this, original, false); + doShowJavaDocInfo((PsiElement)lookupItemObject, false, this, original, null); } } }; - doShowJavaDocInfo(element, false, updateProcessor, original, allowReuse, closeCallback); + doShowJavaDocInfo(element, false, updateProcessor, original, closeCallback); } public void showJavaDocInfo(final Editor editor, @Nullable final PsiFile file, boolean requestFocus) { @@ -267,14 +283,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp public void showJavaDocInfo(final Editor editor, @Nullable final PsiFile file, boolean requestFocus, - final Runnable closeCallback) { - showJavaDocInfo(editor, file, requestFocus, true, closeCallback); - } - - private void showJavaDocInfo(final Editor editor, - @Nullable final PsiFile file, - boolean requestFocus, - final boolean autoupdate, @Nullable final Runnable closeCallback) { + @Nullable final Runnable closeCallback) { myEditor = editor; final Project project = getProject(file); PsiDocumentManager.getInstance(project).commitAllDocuments(); @@ -324,7 +333,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp return; } if (lookupIteObject instanceof PsiElement) { - doShowJavaDocInfo((PsiElement)lookupIteObject, false, this, originalElement, autoupdate, closeCallback); + doShowJavaDocInfo((PsiElement)lookupIteObject, false, this, originalElement, closeCallback); return; } @@ -347,12 +356,12 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp } } else { - doShowJavaDocInfo(element, false, this, originalElement, autoupdate, closeCallback); + doShowJavaDocInfo(element, false, this, originalElement, closeCallback); } } }; - doShowJavaDocInfo(element, requestFocus, updateProcessor, originalElement, autoupdate, closeCallback); + doShowJavaDocInfo(element, requestFocus, updateProcessor, originalElement, closeCallback); } public PsiElement findTargetElement(Editor editor, PsiFile file) { @@ -363,54 +372,56 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp return file != null ? file.findElementAt(editor.getCaretModel().getOffset()) : null; } - private void doShowJavaDocInfo(final PsiElement element, boolean requestFocus, PopupUpdateProcessor updateProcessor, - final PsiElement originalElement, final boolean autoupdate) - { - doShowJavaDocInfo(element, requestFocus, updateProcessor, originalElement, autoupdate, null); - } - private void doShowJavaDocInfo(@NotNull final PsiElement element, boolean requestFocus, PopupUpdateProcessor updateProcessor, final PsiElement originalElement, - final boolean allowReuse, - @Nullable final Runnable closeCallback) - { + @Nullable final Runnable closeCallback) { Project project = getProject(element); storeOriginalElement(project, originalElement, element); + myPreviouslyFocused = WindowManagerEx.getInstanceEx().getFocusedComponent(project); + + JBPopup _oldHint = getDocInfoHint(); if (myToolWindow == null && PropertiesComponent.getInstance().isTrueValue(SHOW_DOCUMENTATION_IN_TOOL_WINDOW)) { createToolWindow(element, originalElement); - return; } else if (myToolWindow != null) { - if (allowReuse && !myToolWindow.isAutoHide()) { - final Content content = myToolWindow.getContentManager().getSelectedContent(); - if (content != null) { - final DocumentationComponent component = (DocumentationComponent)content.getComponent(); - if (component.getElement() != element) { - content.setDisplayName(getTitle(element, true)); - fetchDocInfo(getDefaultCollector(element, originalElement), component, true); + Content content = myToolWindow.getContentManager().getSelectedContent(); + if (content != null) { + DocumentationComponent component = (DocumentationComponent)content.getComponent(); + if (element.getManager().areElementsEquivalent(component.getElement(), element)) { + JComponent preferredFocusableComponent = content.getPreferredFocusableComponent(); + // focus toolwindow on the second actionPerformed + boolean focus = requestFocus || CommandProcessor.getInstance().getCurrentCommand() != null; + if (preferredFocusableComponent != null && focus) { + IdeFocusManager.getInstance(myProject).requestFocus(preferredFocusableComponent, true); } } - - if (!myToolWindow.isVisible()) { - myToolWindow.show(null); + else { + content.setDisplayName(getTitle(element, true)); + fetchDocInfo(getDefaultCollector(element, originalElement), component, true); } - return; } - else { - restorePopupBehavior(); + + if (!myToolWindow.isVisible()) { + myToolWindow.show(null); } } - - final JBPopup _oldHint = getDocInfoHint(); - if (_oldHint != null && _oldHint.isVisible() && _oldHint instanceof AbstractPopup) { - final DocumentationComponent oldComponent = (DocumentationComponent)((AbstractPopup)_oldHint).getComponent(); + else if (_oldHint != null && _oldHint.isVisible() && _oldHint instanceof AbstractPopup) { + DocumentationComponent oldComponent = (DocumentationComponent)((AbstractPopup)_oldHint).getComponent(); fetchDocInfo(getDefaultCollector(element, originalElement), oldComponent); - return; } + else { + showInPopup(element, requestFocus, updateProcessor, originalElement, closeCallback); + } + } + private void showInPopup(@NotNull final PsiElement element, + boolean requestFocus, + PopupUpdateProcessor updateProcessor, + final PsiElement originalElement, + @Nullable final Runnable closeCallback) { final DocumentationComponent component = new DocumentationComponent(this); component.setNavigateCallback(new Consumer<PsiElement>() { @Override @@ -426,26 +437,30 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp @Override public boolean process(JBPopup popup) { createToolWindow(element, originalElement); + myToolWindow.setAutoHide(false); popup.cancel(); return false; } }; - final KeyboardShortcut keyboardShortcut = ActionManagerEx.getInstanceEx().getKeyboardShortcut("QuickJavaDoc"); - final List<Pair<ActionListener, KeyStroke>> actions = - Collections.singletonList(Pair.<ActionListener, KeyStroke>create(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - createToolWindow(element, originalElement); - final JBPopup hint = getDocInfoHint(); - if (hint != null && hint.isVisible()) hint.cancel(); - } - }, keyboardShortcut != null ? keyboardShortcut.getFirstKeyStroke() : null)); // Null keyStroke is ok here + ActionListener actionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + createToolWindow(element, originalElement); + final JBPopup hint = getDocInfoHint(); + if (hint != null && hint.isVisible()) hint.cancel(); + } + }; + List<Pair<ActionListener, KeyStroke>> actions = ContainerUtil.newSmartList(); + AnAction quickDocAction = ActionManagerEx.getInstanceEx().getAction(IdeActions.ACTION_QUICK_JAVADOC); + for (Shortcut shortcut : quickDocAction.getShortcutSet().getShortcuts()) { + if (!(shortcut instanceof KeyboardShortcut)) continue; + actions.add(Pair.create(actionListener, ((KeyboardShortcut)shortcut).getFirstKeyStroke())); + } boolean hasLookup = LookupManager.getActiveLookup(myEditor) != null; final JBPopup hint = JBPopupFactory.getInstance().createComponentPopupBuilder(component, component) - .setRequestFocusCondition(project, NotLookupOrSearchCondition.INSTANCE) - .setProject(project) + .setProject(element.getProject()) .addListener(updateProcessor) .addUserData(updateProcessor) .setKeyboardActions(actions) @@ -490,20 +505,6 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp }) .createPopup(); - - AbstractPopup oldHint = (AbstractPopup)getDocInfoHint(); - if (oldHint != null) { - DocumentationComponent oldComponent = (DocumentationComponent)oldHint.getComponent(); - PsiElement element1 = oldComponent.getElement(); - if (Comparing.equal(element, element1)) { - if (requestFocus) { - component.getComponent().requestFocus(); - } - return; - } - oldHint.cancel(); - } - component.setHint(hint); if (myEditor == null) { @@ -515,7 +516,6 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp fetchDocInfo(getDefaultCollector(element, originalElement), component); myDocInfoHintRef = new WeakReference<JBPopup>(hint); - myPreviouslyFocused = WindowManagerEx.getInstanceEx().getFocusedComponent(project); if (fromQuickSearch() && myPreviouslyFocused != null) { ((ChooseByNameBase.JPanelProvider)myPreviouslyFocused.getParent()).registerHint(hint); @@ -666,11 +666,12 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp private ActionCallback doFetchDocInfo(final DocumentationComponent component, final DocumentationCollector provider, final boolean cancelRequests, final boolean clearHistory) { final ActionCallback callback = new ActionCallback(); + boolean wasEmpty = component.isEmpty(); component.startWait(); if (cancelRequests) { myUpdateDocAlarm.cancelAllRequests(); } - if (component.isEmpty()) { + if (wasEmpty) { component.setText(CodeInsightBundle.message("javadoc.fetching.progress"), null, clearHistory); final AbstractPopup jbPopup = (AbstractPopup)getDocInfoHint(); if (jbPopup != null) { @@ -845,7 +846,26 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp } else if (url.startsWith(PSI_ELEMENT_PROTOCOL)) { final String refText = url.substring(PSI_ELEMENT_PROTOCOL.length()); DocumentationProvider provider = getProviderFromElement(psiElement); - final PsiElement targetElement = provider.getDocumentationElementForLink(manager, refText, psiElement); + PsiElement targetElement = provider.getDocumentationElementForLink(manager, refText, psiElement); + if (targetElement == null) { + for (DocumentationProvider documentationProvider : Extensions.getExtensions(DocumentationProvider.EP_NAME)) { + targetElement = documentationProvider.getDocumentationElementForLink(manager, refText, psiElement); + if (targetElement != null) { + break; + } + } + } + if (targetElement == null) { + for (Language language : Language.getRegisteredLanguages()) { + DocumentationProvider documentationProvider = LanguageDocumentation.INSTANCE.forLanguage(language); + if (documentationProvider != null) { + targetElement = documentationProvider.getDocumentationElementForLink(manager, refText, psiElement); + if (targetElement != null) { + break; + } + } + } + } if (targetElement != null) { fetchDocInfo(getDefaultCollector(targetElement, null), component); } @@ -854,33 +874,33 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp final DocumentationProvider provider = getProviderFromElement(psiElement); boolean processed = false; if (provider instanceof CompositeDocumentationProvider) { - for (DocumentationProvider documentationProvider : ((CompositeDocumentationProvider)provider).getProviders()) { - if (documentationProvider instanceof ExternalDocumentationHandler) { - final ExternalDocumentationHandler externalDocumentationHandler = (ExternalDocumentationHandler)documentationProvider; - if (externalDocumentationHandler.canFetchDocumentationLink(url)) { - fetchDocInfo(new DocumentationCollector() { - @Override - public String getDocumentation() throws Exception { - return externalDocumentationHandler.fetchExternalDocumentation(url, psiElement); - } + for (DocumentationProvider p : ((CompositeDocumentationProvider)provider).getAllProviders()) { + if (!(p instanceof ExternalDocumentationHandler)) continue; - @Override - public PsiElement getElement() { - return psiElement; - } + final ExternalDocumentationHandler externalHandler = (ExternalDocumentationHandler)p; + if (externalHandler.canFetchDocumentationLink(url)) { + fetchDocInfo(new DocumentationCollector() { + @Override + public String getDocumentation() throws Exception { + return externalHandler.fetchExternalDocumentation(url, psiElement); + } - @Nullable - @Override - public String getEffectiveExternalUrl() { - return url; - } - }, component); - processed = true; - } - else if (externalDocumentationHandler.handleExternalLink(manager, url, psiElement)) { - processed = true; - break; - } + @Override + public PsiElement getElement() { + return psiElement; + } + + @Nullable + @Override + public String getEffectiveExternalUrl() { + return url; + } + }, component); + processed = true; + } + else if (externalHandler.handleExternalLink(manager, url, psiElement)) { + processed = true; + break; } } } @@ -979,12 +999,12 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp @Override protected void doUpdateComponent(Editor editor, PsiFile psiFile) { - showJavaDocInfo(editor, psiFile, false, true, null); + showJavaDocInfo(editor, psiFile, false, null); } @Override protected void doUpdateComponent(@NotNull PsiElement element) { - showJavaDocInfo(element, element, true, null); + showJavaDocInfo(element, element, null); } @Override @@ -992,6 +1012,20 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp return getTitle(element, true); } + @Nullable + public Image getElementImage(@NotNull PsiElement element, @NotNull String imageSpec) { + DocumentationProvider provider = getProviderFromElement(element); + if (provider instanceof CompositeDocumentationProvider) { + for (DocumentationProvider p : ((CompositeDocumentationProvider)provider).getAllProviders()) { + if (p instanceof DocumentationProviderEx) { + Image image = ((DocumentationProviderEx)p).getLocalImageForElement(element, imageSpec); + if (image != null) return image; + } + } + } + return null; + } + private interface DocumentationCollector { @Nullable String getDocumentation() throws Exception; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java index 47bf01f2e7c8..0cd18020ad54 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java @@ -301,7 +301,7 @@ public class QuickDocOnMouseOverManager { info.editor.putUserData(PopupFactoryImpl.ANCHOR_POPUP_POSITION, info.editor.offsetToVisualPosition(info.originalElement.getTextRange().getStartOffset())); try { - info.docManager.showJavaDocInfo(info.editor, info.targetElement, info.originalElement, myHintCloseCallback, true, true); + info.docManager.showJavaDocInfo(info.editor, info.targetElement, info.originalElement, myHintCloseCallback, true); myDocumentationManager = new WeakReference<DocumentationManager>(info.docManager); } finally { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocUtil.java new file mode 100644 index 000000000000..064bd020183b --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocUtil.java @@ -0,0 +1,72 @@ +/* + * 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. + * 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.codeInsight.documentation; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowId; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.psi.PsiElement; +import com.intellij.ui.content.Content; +import com.intellij.ui.popup.AbstractPopup; +import com.intellij.util.Producer; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** + * @author gregsh + */ +public class QuickDocUtil { + + public static void updateQuickDocAsync(@NotNull final PsiElement element, @NotNull final Producer<String> docProducer) { + final Project project = element.getProject(); + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + final String documentation = docProducer.produce(); + if (StringUtil.isEmpty(documentation)) return; + // modal dialogs with fragment editors fix: can't guess proper modality state here + //noinspection SSBasedInspection + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + DocumentationManager documentationManager = DocumentationManager.getInstance(project); + DocumentationComponent component; + JBPopup hint = documentationManager.getDocInfoHint(); + if (hint != null) { + component = (DocumentationComponent)((AbstractPopup)hint).getComponent(); + } + else if (documentationManager.hasActiveDockedDocWindow()) { + ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.DOCUMENTATION); + Content selectedContent = toolWindow == null ? null : toolWindow.getContentManager().getSelectedContent(); + component = selectedContent == null ? null : (DocumentationComponent)selectedContent.getComponent(); + } + else { + component = null; + } + if (component != null) { + component.replaceText(documentation, element); + } + } + }); + } + }); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java index eb163245d23b..8010e76335bb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java @@ -44,13 +44,15 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { @Override public Result checkAutoPopup(char charTyped, final Project project, final Editor editor, final PsiFile file) { - CompletionPhase oldPhase = CompletionServiceImpl.getCompletionPhase(); + LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor); - if (oldPhase instanceof CompletionPhase.CommittingDocuments && ((CompletionPhase.CommittingDocuments)oldPhase).isRestartingCompletion()) { - return Result.STOP; + if (LOG.isDebugEnabled()) { + LOG.debug("checkAutoPopup: character=" + charTyped + ";"); + LOG.debug("phase=" + CompletionServiceImpl.getCompletionPhase()); + LOG.debug("lookup=" + lookup); + LOG.debug("currentCompletion=" + CompletionServiceImpl.getCompletionService().getCurrentCompletion()); } - LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor); if (lookup != null) { if (editor.getSelectionModel().hasSelection()) { lookup.performGuardedChange(new Runnable() { @@ -68,9 +70,6 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { return Result.STOP; } - if (CompletionServiceImpl.isPhase(CompletionPhase.CommittingDocuments.class)) { - CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); - } return Result.CONTINUE; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java index 5f416dd307c4..1149576e4806 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java @@ -29,6 +29,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.ScrollType; @@ -49,6 +50,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.NotNullFunction; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import static com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate.CANNOT_JOIN; @@ -61,66 +63,65 @@ public class JoinLinesHandler extends EditorWriteActionHandler { myOriginalHandler = originalHandler; } - private static TextRange findStartAndEnd(CharSequence text, int start, int end, int maxoffset) { + @NotNull + private static TextRange findStartAndEnd(@NotNull CharSequence text, int start, int end, int maxoffset) { while (start > 0 && (text.charAt(start) == ' ' || text.charAt(start) == '\t')) start--; while (end < maxoffset && (text.charAt(end) == ' ' || text.charAt(end) == '\t')) end++; return new TextRange(start, end); } @Override - public void executeWriteAction(final Editor editor, final DataContext dataContext) { + public void executeWriteAction(@NotNull final Editor editor, @Nullable Caret caret, final DataContext dataContext) { + assert caret != null; if (!(editor.getDocument() instanceof DocumentEx)) { - myOriginalHandler.execute(editor, dataContext); + myOriginalHandler.execute(editor, caret, dataContext); return; } final DocumentEx doc = (DocumentEx)editor.getDocument(); final Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(editor.getContentComponent())); - if (project == null) { - return; - } - - LogicalPosition caretPosition = editor.getCaretModel().getLogicalPosition(); + if (project == null) return; final PsiDocumentManager docManager = PsiDocumentManager.getInstance(project); PsiFile psiFile = docManager.getPsiFile(doc); if (psiFile == null) { - myOriginalHandler.execute(editor, dataContext); + myOriginalHandler.execute(editor, caret, dataContext); return; } + LogicalPosition caretPosition = caret.getLogicalPosition(); int startLine = caretPosition.line; int endLine = startLine + 1; - if (editor.getSelectionModel().hasSelection()) { - startLine = doc.getLineNumber(editor.getSelectionModel().getSelectionStart()); - endLine = doc.getLineNumber(editor.getSelectionModel().getSelectionEnd()); - if (doc.getLineStartOffset(endLine) == editor.getSelectionModel().getSelectionEnd()) endLine--; + if (caret.hasSelection()) { + startLine = doc.getLineNumber(caret.getSelectionStart()); + endLine = doc.getLineNumber(caret.getSelectionEnd()); + if (doc.getLineStartOffset(endLine) == caret.getSelectionEnd()) endLine--; } final int startReformatOffset = CharArrayUtil.shiftBackward(doc.getCharsSequence(), doc.getLineEndOffset(startLine), " \t"); CodeEditUtil.setNodeReformatStrategy(new NotNullFunction<ASTNode, Boolean>() { @NotNull @Override - public Boolean fun(ASTNode node) { + public Boolean fun(@NotNull ASTNode node) { return node.getTextRange().getStartOffset() >= startReformatOffset; } }); try { - doJob(editor, doc, project, docManager, psiFile, startLine, endLine); + doJob(editor, doc, caret, project, docManager, psiFile, startLine, endLine); } finally { CodeEditUtil.setNodeReformatStrategy(null); } } - private static void doJob(Editor editor, - DocumentEx doc, - Project project, - PsiDocumentManager docManager, - PsiFile psiFile, + private static void doJob(@NotNull Editor editor, + @NotNull DocumentEx doc, + @NotNull Caret caret, + @NotNull Project project, + @NotNull PsiDocumentManager docManager, + @NotNull PsiFile psiFile, int startLine, - int endLine) - { + int endLine) { int caretRestoreOffset = -1; // joining lines, several times if selection is multiline for (int i = startLine; i < endLine; i++) { @@ -262,17 +263,19 @@ public class JoinLinesHandler extends EditorWriteActionHandler { } docManager.commitDocument(doc); // cheap on an already-committed doc - if (editor.getSelectionModel().hasSelection()) { - editor.getCaretModel().moveToOffset(editor.getSelectionModel().getSelectionEnd()); + if (caret.hasSelection()) { + caret.moveToOffset(caret.getSelectionEnd()); } else if (caretRestoreOffset != CANNOT_JOIN) { - editor.getCaretModel().moveToOffset(caretRestoreOffset); - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); - editor.getSelectionModel().removeSelection(); + caret.moveToOffset(caretRestoreOffset); + if (caret == editor.getCaretModel().getPrimaryCaret()) { // performance + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + } + caret.removeSelection(); } } - private static boolean isCommentElement(final PsiElement element) { + private static boolean isCommentElement(@Nullable final PsiElement element) { return element != null && PsiTreeUtil.getParentOfType(element, PsiComment.class, false) != null; } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternDialog.java index abdcf6c44047..f736a02d83bf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternDialog.java @@ -1,3 +1,18 @@ +/* + * 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. + * 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.codeInsight.generation; import com.intellij.codeInsight.template.Template; @@ -13,6 +28,7 @@ import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.treeStructure.SimpleTree; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -55,8 +71,9 @@ public class GenerateByPatternDialog extends DialogWrapper { }; myTree.setRootVisible(false); myTree.setCellRenderer(new DefaultTreeCellRenderer() { + @NotNull @Override - public Component getTreeCellRendererComponent(JTree tree, + public Component getTreeCellRendererComponent(@NotNull JTree tree, Object value, boolean sel, boolean expanded, @@ -78,7 +95,7 @@ public class GenerateByPatternDialog extends DialogWrapper { myTree.setModel(new DefaultTreeModel(root)); myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { @Override - public void valueChanged(TreeSelectionEvent e) { + public void valueChanged(@NotNull TreeSelectionEvent e) { update(); } }); @@ -141,6 +158,7 @@ public class GenerateByPatternDialog extends DialogWrapper { private DefaultMutableTreeNode createNode(@Nullable PatternDescriptor descriptor) { DefaultMutableTreeNode root = new DefaultMutableTreeNode(descriptor) { + @NotNull @Override public String toString() { Object object = getUserObject(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java index 786c14b68201..2de362f14074 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java @@ -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. @@ -23,6 +23,8 @@ import org.jetbrains.annotations.Nullable; /** * @author yole + * + * @see com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactoryBase */ public interface HighlightUsagesHandlerFactory { ExtensionPointName<HighlightUsagesHandlerFactory> EP_NAME = ExtensionPointName.create("com.intellij.highlightUsagesHandlerFactory"); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactoryBase.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactoryBase.java new file mode 100644 index 000000000000..83c6cf35c57e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactoryBase.java @@ -0,0 +1,40 @@ +/* + * 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. + * 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.codeInsight.highlighting; + +import com.intellij.codeInsight.TargetElementUtilBase; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Konstantin Bulenkov + */ +public abstract class HighlightUsagesHandlerFactoryBase implements HighlightUsagesHandlerFactory { + @Nullable + @Override + public final HighlightUsagesHandlerBase createHighlightUsagesHandler(Editor editor, PsiFile file) { + int offset = TargetElementUtilBase.adjustOffset(file, editor.getDocument(), editor.getCaretModel().getOffset()); + PsiElement target = file.findElementAt(offset); + if (target == null) return null; + return createHighlightUsagesHandler(editor, file, target); + } + + @Nullable + public abstract HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file, @NotNull PsiElement target); +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java index 4e1a8e958d91..b1ad07f906d2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java @@ -22,7 +22,6 @@ import com.intellij.lang.parameterInfo.ParameterInfoUIContextEx; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.ui.Gray; import com.intellij.ui.JBColor; @@ -296,47 +295,50 @@ public class ParameterInfoComponent extends JPanel { public String setup(final String[] texts, final EnumSet<ParameterInfoUIContextEx.Flag>[] flags, final Color background) { StringBuilder buf = new StringBuilder(); removeAll(); - final String[] lines = UIUtil.splitText(StringUtil.join(texts), getFontMetrics(BOLD_FONT), myWidthLimit, ','); - + setBackground(background); int index = 0; int curOffset = 0; - - myOneLineComponents = new OneLineComponent[lines.length]; + final ArrayList<OneLineComponent> components = new ArrayList<OneLineComponent>(); Map<TextRange, ParameterInfoUIContextEx.Flag> flagsMap = new TreeMap<TextRange, ParameterInfoUIContextEx.Flag>(TEXT_RANGE_COMPARATOR); - int added = 0; + String line = ""; for (int i = 0; i < texts.length; i++) { - String line = escapeString(texts[i]); - if (lines.length <= index) break; - String text = lines[index]; - final int paramCount = StringUtil.split(text, ", ").size(); + String paramText = escapeString(texts[i]); + if (paramText == null) break; + line += texts[i]; final EnumSet<ParameterInfoUIContextEx.Flag> flag = flags[i]; if (flag.contains(ParameterInfoUIContextEx.Flag.HIGHLIGHT)) { - flagsMap.put(TextRange.create(curOffset, curOffset + line.trim().length()), ParameterInfoUIContextEx.Flag.HIGHLIGHT); + flagsMap.put(TextRange.create(curOffset, curOffset + paramText.trim().length()), ParameterInfoUIContextEx.Flag.HIGHLIGHT); } if (flag.contains(ParameterInfoUIContextEx.Flag.DISABLE)) { - flagsMap.put(TextRange.create(curOffset, curOffset + line.trim().length()), ParameterInfoUIContextEx.Flag.DISABLE); + flagsMap.put(TextRange.create(curOffset, curOffset + paramText.trim().length()), ParameterInfoUIContextEx.Flag.DISABLE); } if (flag.contains(ParameterInfoUIContextEx.Flag.STRIKEOUT)) { - flagsMap.put(TextRange.create(curOffset, curOffset + line.trim().length()), ParameterInfoUIContextEx.Flag.STRIKEOUT); + flagsMap.put(TextRange.create(curOffset, curOffset + paramText.trim().length()), ParameterInfoUIContextEx.Flag.STRIKEOUT); } - curOffset += line.length(); - if (i == paramCount + added - 1) { - myOneLineComponents[index] = new OneLineComponent(); - setBackground(background); - buf.append(myOneLineComponents[index].setup(escapeString(text), flagsMap, background)); - add(myOneLineComponents[index], new GridBagConstraints(0, index, 1, 1, 1, 0, GridBagConstraints.WEST, + curOffset += paramText.length(); + if (line.length() >= 50) { + final OneLineComponent component = new OneLineComponent(); + buf.append(component.setup(escapeString(line), flagsMap, background)); + add(component, new GridBagConstraints(0, index, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); index += 1; flagsMap.clear(); - curOffset = 1; - added += paramCount; + curOffset = 0; + line = ""; + components.add(component); } } + final OneLineComponent component = new OneLineComponent(); + buf.append(component.setup(escapeString(line), flagsMap, background)); + add(component, new GridBagConstraints(0, index, 1, 1, 1, 0, GridBagConstraints.WEST, + GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + components.add(component); + myOneLineComponents = components.toArray(new OneLineComponent[components.size()]); return buf.toString(); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java index 4a7abe355380..afd7b230621c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java @@ -37,7 +37,6 @@ import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; @@ -48,7 +47,6 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.reference.SoftReference; import com.intellij.ui.popup.AbstractPopup; -import com.intellij.ui.popup.NotLookupOrSearchCondition; import com.intellij.ui.popup.PopupPositionManager; import com.intellij.ui.popup.PopupUpdateProcessor; import com.intellij.usages.UsageView; @@ -274,7 +272,6 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { }; popup = JBPopupFactory.getInstance().createComponentPopupBuilder(component, component.getPreferredFocusableComponent()) - .setRequestFocusCondition(project, NotLookupOrSearchCondition.INSTANCE) .setProject(project) .addListener(updateProcessor) .addUserData(updateProcessor) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java index 62e3bcba3a22..d168002f97a7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java @@ -30,11 +30,15 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.*; +import com.intellij.psi.ElementManipulators; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.impl.source.tree.injected.Place; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -93,14 +97,17 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction { } public QuickEditHandler invokeImpl(@NotNull final Project project, final Editor editor, PsiFile file) throws IncorrectOperationException { - final int offset = editor.getCaretModel().getOffset(); - final Pair<PsiElement, TextRange> pair = getRangePair(file, editor); - assert pair != null; - final PsiFile injectedFile = (PsiFile)pair.first; - final int injectedOffset = ((DocumentWindow)PsiDocumentManager.getInstance(project).getDocument(injectedFile)).hostToInjected(offset); + int offset = editor.getCaretModel().getOffset(); + Pair<PsiElement, TextRange> pair = ObjectUtils.assertNotNull(getRangePair(file, editor)); + + PsiFile injectedFile = (PsiFile)pair.first; QuickEditHandler handler = getHandler(project, injectedFile, editor, file); + if (!ApplicationManager.getApplication().isUnitTestMode()) { - handler.navigate(injectedOffset); + DocumentWindow documentWindow = InjectedLanguageUtil.getDocumentWindow(injectedFile); + if (documentWindow != null) { + handler.navigate(documentWindow.hostToInjected(offset)); + } } return handler; } @@ -124,12 +131,15 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction { return handler; } - public static QuickEditHandler getExistingHandler(PsiFile injectedFile) { + public static QuickEditHandler getExistingHandler(@NotNull PsiFile injectedFile) { Place shreds = InjectedLanguageUtil.getShreds(injectedFile); - if (shreds == null) return null; + DocumentWindow documentWindow = InjectedLanguageUtil.getDocumentWindow(injectedFile); + if (shreds == null || documentWindow == null) return null; + TextRange hostRange = TextRange.create(shreds.get(0).getHostRangeMarker().getStartOffset(), shreds.get(shreds.size() - 1).getHostRangeMarker().getEndOffset()); for (Editor editor : EditorFactory.getInstance().getAllEditors()) { + if (editor.getDocument() != documentWindow.getDelegate()) continue; QuickEditHandler handler = editor.getUserData(QUICK_EDIT_HANDLER); if (handler != null && handler.changesRange(hostRange)) return handler; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java index 2c5d8642e46d..517f23c5a198 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java @@ -360,7 +360,7 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable { private void commitToOriginal() { if (!isValid()) return; - VirtualFile origVirtualFile = PsiUtilCore.getVirtualFile(ObjectUtils.assertNotNull(myNewFile.getContext())); + VirtualFile origVirtualFile = PsiUtilCore.getVirtualFile(myNewFile.getContext()); myCommittingToOriginal = true; try { if (origVirtualFile == null || !ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(origVirtualFile).hasReadonlyFiles()) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionManagerImpl.java index 46842af23c34..ca0a51112f98 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionManagerImpl.java @@ -20,12 +20,13 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.IntentionActionBean; import com.intellij.codeInsight.intention.IntentionManager; +import com.intellij.codeInspection.GlobalInspectionTool; +import com.intellij.codeInspection.GlobalSimpleInspectionTool; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.actions.CleanupInspectionIntention; import com.intellij.codeInspection.actions.RunInspectionIntention; -import com.intellij.codeInspection.ex.DisableInspectionToolAction; -import com.intellij.codeInspection.ex.EditInspectionToolsSettingsAction; -import com.intellij.codeInspection.ex.EditInspectionToolsSettingsInSuppressedPlaceIntention; +import com.intellij.codeInspection.ex.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.ExtensionPoint; @@ -181,6 +182,32 @@ public class IntentionManagerImpl extends IntentionManager { return options; } + @Nullable + @Override + public IntentionAction createFixAllIntention(InspectionToolWrapper toolWrapper, IntentionAction action) { + if (toolWrapper instanceof LocalInspectionToolWrapper) { + Class aClass = action.getClass(); + if (action instanceof QuickFixWrapper) { + aClass = ((QuickFixWrapper)action).getFix().getClass(); + } + return new CleanupInspectionIntention(toolWrapper, aClass, action.getText()); + } + else if (toolWrapper instanceof GlobalInspectionToolWrapper) { + GlobalInspectionTool wrappedTool = ((GlobalInspectionToolWrapper)toolWrapper).getTool(); + if (wrappedTool instanceof GlobalSimpleInspectionTool && (action instanceof LocalQuickFix || action instanceof QuickFixWrapper)) { + Class aClass = action.getClass(); + if (action instanceof QuickFixWrapper) { + aClass = ((QuickFixWrapper)action).getFix().getClass(); + } + return new CleanupInspectionIntention(toolWrapper, aClass, action.getText()); + } + } + else { + throw new AssertionError("unknown tool: " + toolWrapper); + } + return null; + } + @Override @NotNull public LocalQuickFix convertToFix(@NotNull final IntentionAction action) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 9a71909fcca8..869886d26523 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -776,15 +776,13 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, @Override public void valueChanged(@NotNull ListSelectionEvent e){ - final LookupElement item = getCurrentItem(); - if (oldItem != item && !myList.isEmpty()) { // do not update on temporary model wipe - fireCurrentItemChanged(item); - if (myDisposed) { //a listener may have decided to close us, what can we do? - return; - } + if (!myUpdating) { + final LookupElement item = getCurrentItem(); + fireCurrentItemChanged(oldItem, item); oldItem = item; } } + }); new ClickListener() { @@ -876,9 +874,9 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, } } - void fireCurrentItemChanged(LookupElement item){ - if (!myListeners.isEmpty()){ - LookupEvent event = new LookupEvent(this, item, (char)0); + private void fireCurrentItemChanged(@Nullable LookupElement oldItem, @Nullable LookupElement currentItem) { + if (oldItem != currentItem && !myListeners.isEmpty()) { + LookupEvent event = new LookupEvent(this, currentItem, (char)0); for (LookupListener listener : myListeners) { listener.currentItemChanged(event); } @@ -1088,6 +1086,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, public void refreshUi(boolean mayCheckReused, boolean onExplicitAction) { assert !myUpdating; + LookupElement prevItem = getCurrentItem(); myUpdating = true; try { final boolean reused = mayCheckReused && checkReused(); @@ -1100,6 +1099,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, } finally { myUpdating = false; + fireCurrentItemChanged(prevItem, getCurrentItem()); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index 2f56d3714943..5486a07f6f18 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -455,7 +455,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent { @Override public void showDocInfo(@NotNull DocumentationManager docManager) { - docManager.showJavaDocInfo(myTargetElement, myElementAtPointer, true, null); + docManager.showJavaDocInfo(myTargetElement, myElementAtPointer, null); docManager.setAllowContentUpdateFromContext(false); } } @@ -1115,7 +1115,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent { if (hint != null) { hint.hide(true); } - myDocumentationManager.showJavaDocInfo(targetElement, myContext, true, null); + myDocumentationManager.showJavaDocInfo(targetElement, myContext, null); } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java index 6ef571f62a03..0d49a89d9c43 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java @@ -42,6 +42,7 @@ import com.intellij.psi.PsiNamedElement; import com.intellij.ui.CollectionListModel; import com.intellij.ui.JBListWithHintProvider; import com.intellij.ui.popup.AbstractPopup; +import com.intellij.ui.popup.HintUpdateSupply; import com.intellij.usages.UsageView; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; @@ -179,7 +180,7 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler { setCancelCallback(new Computable<Boolean>() { @Override public Boolean compute() { - list.hideHint(); + HintUpdateSupply.hideHint(list); return true; } }). diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/ImplementationSearcher.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/ImplementationSearcher.java index 504ec1b13c41..a3fbbc62dd85 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/ImplementationSearcher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/ImplementationSearcher.java @@ -125,13 +125,12 @@ public class ImplementationSearcher { public static class FirstImplementationsSearcher extends ImplementationSearcher { @Override protected PsiElement[] searchDefinitions(final PsiElement element, final Editor editor) { - final PsiElement[][] result = new PsiElement[1][]; - if (canShowPopupWithOneItem(element)) { return new PsiElement[]{element}; } final PsiElementProcessor.CollectElementsWithLimit<PsiElement> collectProcessor = new PsiElementProcessor.CollectElementsWithLimit<PsiElement>(2, new THashSet<PsiElement>()); + final PsiElement[][] result = new PsiElement[1][]; if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { @@ -139,8 +138,7 @@ public class ImplementationSearcher { DefinitionsScopedSearch.search(element, getSearchScope(element, editor)).forEach(new PsiElementProcessorAdapter<PsiElement>(collectProcessor){ @Override public boolean processInReadAction(PsiElement element) { - if (!accept(element)) return true; - return super.processInReadAction(element); + return !accept(element) || super.processInReadAction(element); } }); result[0] = collectProcessor.toArray(); @@ -165,7 +163,7 @@ public class ImplementationSearcher { } } - public static abstract class BackgroundableImplementationSearcher extends ImplementationSearcher { + public abstract static class BackgroundableImplementationSearcher extends ImplementationSearcher { @Override protected PsiElement[] searchDefinitions(final PsiElement element, Editor editor) { final CommonProcessors.CollectProcessor<PsiElement> processor = new CommonProcessors.CollectProcessor<PsiElement>() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElementImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElementImpl.java index 9ce023727820..2ddf92cfe1ff 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElementImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -24,7 +24,7 @@ public class LiveTemplateLookupElementImpl extends LiveTemplateLookupElement { private final TemplateImpl myTemplate; public LiveTemplateLookupElementImpl(@NotNull TemplateImpl template, boolean sudden) { - super(template.getKey(), StringUtil.notNullize(template.getDescription()), sudden, false); + super(template.getKey(), StringUtil.notNullize(template.getDescription()), sudden, LiveTemplateCompletionContributor.shouldShowAllTemplates()); myTemplate = template; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java index 1988c9d1d8a4..c14eca966e5f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 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. @@ -28,7 +28,6 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.popup.JBPopup; @@ -52,7 +51,6 @@ import com.intellij.util.ui.tree.TreeUtil; import com.intellij.util.ui.update.Activatable; import com.intellij.util.ui.update.UiNotifyConnector; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; @@ -182,7 +180,7 @@ public class LiveTemplateSettingsEditor extends JPanel { myEditVariablesButton.addActionListener( new ActionListener(){ @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { editVariables(); } } @@ -201,7 +199,7 @@ public class LiveTemplateSettingsEditor extends JPanel { myTemplate.parseSegments(); } - @Nullable + @NotNull private JComponent createNorthPanel() { JPanel panel = new JPanel(new GridBagLayout()); @@ -240,7 +238,7 @@ public class LiveTemplateSettingsEditor extends JPanel { myExpandByCombo = new ComboBox(new String[]{myDefaultShortcutItem, SPACE, TAB, ENTER}); myExpandByCombo.addItemListener(new ItemListener() { @Override - public void itemStateChanged(ItemEvent e) { + public void itemStateChanged(@NotNull ItemEvent e) { Object selectedItem = myExpandByCombo.getSelectedItem(); if(myDefaultShortcutItem.equals(selectedItem)) { myTemplate.setShortcutChar(TemplateSettings.DEFAULT_CHAR); @@ -278,7 +276,7 @@ public class LiveTemplateSettingsEditor extends JPanel { cb.setSelected(myOptions.get(processor).booleanValue()); cb.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { myOptions.put(processor, cb.isSelected()); } }); @@ -469,14 +467,7 @@ public class LiveTemplateSettingsEditor extends JPanel { } private void updateHighlighter() { - List<TemplateContextType> applicableContexts = getApplicableContexts(); - if (!applicableContexts.isEmpty()) { - TemplateContext contextByType = new TemplateContext(); - contextByType.setEnabled(applicableContexts.get(0), true); - TemplateEditorUtil.setHighlighter(myTemplateEditor, contextByType); - return; - } - ((EditorEx) myTemplateEditor).repaint(0, myTemplateEditor.getDocument().getTextLength()); + TemplateEditorUtil.setHighlighter(myTemplateEditor, ContainerUtil.getFirstItem(getApplicableContexts())); } private void validateEditVariablesButton() { @@ -520,7 +511,7 @@ public class LiveTemplateSettingsEditor extends JPanel { myCbReformat.setSelected(myTemplate.isToReformat()); myCbReformat.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { myTemplate.setToReformat(myCbReformat.isSelected()); } }); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateEditorUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateEditorUtil.java index 1570bb18c040..dd30df23a493 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateEditorUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateEditorUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -18,7 +18,6 @@ package com.intellij.codeInsight.template.impl; import com.intellij.codeInsight.template.TemplateContextType; import com.intellij.ide.DataManager; -import com.intellij.lexer.CompositeLexer; import com.intellij.lexer.Lexer; import com.intellij.lexer.MergingLexerAdapter; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -31,7 +30,8 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter; +import com.intellij.openapi.editor.ex.util.LayerDescriptor; +import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter; import com.intellij.openapi.editor.highlighter.EditorHighlighter; import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -42,6 +42,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -87,54 +88,41 @@ public class TemplateEditorUtil { if (file != null) { EditorHighlighter highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(file, scheme, project); ((EditorEx) editor).setHighlighter(highlighter); + } return editor; } - public static void setHighlighter(Editor editor, TemplateContext templateContext) { - SyntaxHighlighter baseHighlighter = null; - for(TemplateContextType type: TemplateManagerImpl.getAllContextTypes()) { - if (templateContext.isEnabled(type)) { - baseHighlighter = type.createHighlighter(); - if (baseHighlighter != null) break; + public static void setHighlighter(Editor editor, @Nullable TemplateContext templateContext) { + SyntaxHighlighter highlighter = null; + if (templateContext != null) { + for(TemplateContextType type: TemplateManagerImpl.getAllContextTypes()) { + if (templateContext.isEnabled(type)) { + highlighter = type.createHighlighter(); + if (highlighter != null) break; + } } } - if (baseHighlighter == null) { - baseHighlighter = new PlainSyntaxHighlighter(); - } - - SyntaxHighlighter highlighter = createTemplateTextHighlighter(baseHighlighter); - ((EditorEx)editor).setHighlighter(new LexerEditorHighlighter(highlighter, EditorColorsManager.getInstance().getGlobalScheme())); + setHighlighter((EditorEx)editor, highlighter); } - private final static TokenSet TOKENS_TO_MERGE = TokenSet.create(TemplateTokenType.TEXT); + public static void setHighlighter(@NotNull Editor editor, @Nullable TemplateContextType templateContextType) { + setHighlighter((EditorEx)editor, templateContextType != null ? templateContextType.createHighlighter() : null); + } - private static SyntaxHighlighter createTemplateTextHighlighter(final SyntaxHighlighter original) { - return new TemplateHighlighter(original); + private static void setHighlighter(EditorEx editor, @Nullable SyntaxHighlighter highlighter) { + EditorColorsScheme editorColorsScheme = EditorColorsManager.getInstance().getGlobalScheme(); + LayeredLexerEditorHighlighter layeredHighlighter = new LayeredLexerEditorHighlighter(new TemplateHighlighter(), editorColorsScheme); + layeredHighlighter.registerLayer(TemplateTokenType.TEXT, new LayerDescriptor(ObjectUtils.notNull(highlighter, new PlainSyntaxHighlighter()), "")); + editor.setHighlighter(layeredHighlighter); } private static class TemplateHighlighter extends SyntaxHighlighterBase { private final Lexer myLexer; - private final SyntaxHighlighter myOriginalHighlighter; - - public TemplateHighlighter(SyntaxHighlighter original) { - myOriginalHighlighter = original; - Lexer originalLexer = original.getHighlightingLexer(); - Lexer templateLexer = new TemplateTextLexer(); - templateLexer = new MergingLexerAdapter(templateLexer, TOKENS_TO_MERGE); - - myLexer = new CompositeLexer(originalLexer, templateLexer) { - @Override - protected IElementType getCompositeTokenType(IElementType type1, IElementType type2) { - if (type2 == TemplateTokenType.VARIABLE) { - return type2; - } - else { - return type1; - } - } - }; + + public TemplateHighlighter() { + myLexer = new MergingLexerAdapter(new TemplateTextLexer(), TokenSet.create(TemplateTokenType.TEXT)); } @Override @@ -146,11 +134,7 @@ public class TemplateEditorUtil { @Override @NotNull public TextAttributesKey[] getTokenHighlights(IElementType tokenType) { - if (tokenType == TemplateTokenType.VARIABLE) { - return pack(myOriginalHighlighter.getTokenHighlights(tokenType), TemplateColors.TEMPLATE_VARIABLE_ATTRIBUTES); - } - - return myOriginalHighlighter.getTokenHighlights(tokenType); + return tokenType == TemplateTokenType.VARIABLE ? pack(TemplateColors.TEMPLATE_VARIABLE_ATTRIBUTES) : EMPTY; } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java index e5f2fd4ae23d..abf28256aaef 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java @@ -105,7 +105,7 @@ public class TemplateSettings implements PersistentStateComponent<Element>, Expo private int myMaxKeyLength = 0; private char myDefaultShortcutChar = TAB_CHAR; private final SchemesManager<TemplateGroup, TemplateGroup> mySchemesManager; - private static final String FILE_SPEC = "$ROOT_CONFIG$/templates"; + private static final String FILE_SPEC = StoragePathMacros.ROOT_CONFIG + "/templates"; public static class TemplateKey { private String groupName; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixDescriptionPanel.form b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixDescriptionPanel.form index cd60a7de70f4..519481484dc7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixDescriptionPanel.form +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixDescriptionPanel.form @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.codeInsight.template.postfix.settings.PostfixDescriptionPanel"> - <grid id="d0bf1" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> + <grid id="d0bf1" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> <xy x="26" y="23" width="498" height="354"/> @@ -19,7 +19,9 @@ <xy id="a6fdd" binding="myAfterPanel" layout-manager="XYLayout" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> - <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> + <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"> + <minimum-size width="-1" height="125"/> + </grid> </constraints> <properties/> <border type="none"/> @@ -28,7 +30,9 @@ <xy id="fa495" binding="myBeforePanel" layout-manager="XYLayout" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> - <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> + <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"> + <minimum-size width="-1" height="125"/> + </grid> </constraints> <properties/> <border type="none"/> @@ -77,6 +81,11 @@ </component> </children> </grid> + <vspacer id="53ca7"> + <constraints> + <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/> + </constraints> + </vspacer> </children> </grid> </form> diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java index 5cd822130538..0190fadbcf02 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java @@ -22,6 +22,7 @@ import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement; import com.intellij.codeInsight.template.impl.TemplateSettings; import com.intellij.codeInsight.template.postfix.completion.PostfixTemplateLookupElement; import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings; +import com.intellij.diagnostic.AttachmentFactory; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.lang.Language; import com.intellij.openapi.application.ApplicationManager; @@ -137,7 +138,8 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { } // don't care about errors in multiCaret mode else if (editor.getCaretModel().getAllCarets().size() == 1) { - LOG.error("Template not found by key: " + key); + LOG.error("Template not found by key: " + key + "; offset = " + callback.getOffset(), + AttachmentFactory.createAttachment(callback.getFile().getVirtualFile())); } return; } @@ -145,7 +147,8 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { // don't care about errors in multiCaret mode if (editor.getCaretModel().getAllCarets().size() == 1) { - LOG.error("Template not found by key: " + key); + LOG.error("Template not found by key: " + key + "; offset = " + callback.getOffset(), + AttachmentFactory.createAttachment(callback.getFile().getVirtualFile())); } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java new file mode 100644 index 000000000000..b6a68ef88fb0 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java @@ -0,0 +1,128 @@ +/* + * Copyright 2000-2013 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.codeInspection.actions; + +import com.intellij.codeInsight.FileModificationService; +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.codeInsight.intention.EmptyIntentionAction; +import com.intellij.codeInsight.intention.HighPriorityAction; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.ex.InspectionToolWrapper; +import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.progress.EmptyProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * User: anna + * Date: 21-Feb-2006 + */ +public class CleanupInspectionIntention implements IntentionAction, HighPriorityAction { + private final InspectionToolWrapper myToolWrapper; + private final Class myQuickfixClass; + private final String myText; + + public CleanupInspectionIntention(@NotNull InspectionToolWrapper toolWrapper, @NotNull Class quickFixClass, String text) { + myToolWrapper = toolWrapper; + myQuickfixClass = quickFixClass; + myText = text; + } + + @Override + @NotNull + public String getText() { + return InspectionsBundle.message("fix.all.inspection.problems.in.file", myToolWrapper.getDisplayName()); + } + + @Override + @NotNull + public String getFamilyName() { + return getText(); + } + + @Override + public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { + if (!FileModificationService.getInstance().preparePsiElementForWrite(file)) return; + final List<ProblemDescriptor> descriptions = + ProgressManager.getInstance().runProcess(new Computable<List<ProblemDescriptor>>() { + @Override + public List<ProblemDescriptor> compute() { + InspectionManager inspectionManager = InspectionManager.getInstance(project); + return InspectionEngine.runInspectionOnFile(file, myToolWrapper, inspectionManager.createNewGlobalContext(false)); + } + }, new EmptyProgressIndicator()); + + Collections.sort(descriptions, new Comparator<CommonProblemDescriptor>() { + @Override + public int compare(final CommonProblemDescriptor o1, final CommonProblemDescriptor o2) { + final ProblemDescriptorBase d1 = (ProblemDescriptorBase)o1; + final ProblemDescriptorBase d2 = (ProblemDescriptorBase)o2; + return d2.getTextRange().getStartOffset() - d1.getTextRange().getStartOffset(); + } + }); + boolean applicableFixFound = false; + for (final ProblemDescriptor descriptor : descriptions) { + final QuickFix[] fixes = descriptor.getFixes(); + if (fixes != null && fixes.length > 0) { + for (final QuickFix<CommonProblemDescriptor> fix : fixes) { + if (fix != null && fix.getClass().isAssignableFrom(myQuickfixClass)) { + final PsiElement element = descriptor.getPsiElement(); + if (element != null && element.isValid()) { + applicableFixFound = true; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + fix.applyFix(project, descriptor); + } + }); + PsiDocumentManager.getInstance(project).commitAllDocuments(); + } + break; + } + } + } + } + + if (!applicableFixFound) { + HintManager.getInstance().showErrorHint(editor, "Unfortunately '" + myText + "' is currently not available for batch mode"); + } + } + + @Override + public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) { + return myQuickfixClass != EmptyIntentionAction.class && + !(myToolWrapper instanceof LocalInspectionToolWrapper && ((LocalInspectionToolWrapper)myToolWrapper).isUnfair()); + } + + @Override + public boolean startInWriteAction() { + return false; + } +} 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 090d83389b6c..695c2a72d200 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -58,7 +58,6 @@ import com.intellij.psi.*; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtilCore; import com.intellij.ui.content.*; import com.intellij.util.Processor; import com.intellij.util.SequentialModalProgressTask; @@ -81,7 +80,7 @@ import java.util.*; public class GlobalInspectionContextImpl extends GlobalInspectionContextBase implements GlobalInspectionContext { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.GlobalInspectionContextImpl"); - private static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("Inspection Results", ToolWindowId.INSPECTION, true); + private static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("Inspection Results", ToolWindowId.INSPECTION); private final NotNullLazyValue<ContentManager> myContentManager; private InspectionResultsView myView = null; private Content myContent = null; @@ -641,6 +640,8 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp final Project project, final Runnable postRunnable, final String commandName) { + final int fileCount = scope.getFileCount(); + final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); final List<LocalInspectionToolWrapper> lTools = new ArrayList<LocalInspectionToolWrapper>(); final LinkedHashMap<PsiFile, List<HighlightInfo>> results = new LinkedHashMap<PsiFile, List<HighlightInfo>>(); @@ -655,8 +656,12 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp range = null; } scope.accept(new PsiElementVisitor() { + private int myCount = 0; @Override public void visitFile(PsiFile file) { + if (progressIndicator != null) { + progressIndicator.setFraction(((double)++ myCount)/fileCount); + } if (isBinary(file)) return; for (final Tools tools : profile.getAllEnabledInspectionTools(project)) { if (tools.getTool().getTool() instanceof CleanupLocalInspectionTool) { @@ -704,7 +709,9 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp CommandProcessor.getInstance().executeCommand(project, new Runnable() { @Override public void run() { - CommandProcessor.getInstance().markCurrentCommandAsGlobal(project); + if (commandName != null) { + CommandProcessor.getInstance().markCurrentCommandAsGlobal(project); + } ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { @@ -718,7 +725,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp }, commandName, null); } }; - if (ApplicationManager.getApplication().isUnitTestMode()) { + if (ApplicationManager.getApplication().isDispatchThread()) { runnable.run(); } else { ApplicationManager.getApplication().invokeLater(runnable); diff --git a/platform/lang-impl/src/com/intellij/conversion/impl/ui/ConvertProjectDialog.java b/platform/lang-impl/src/com/intellij/conversion/impl/ui/ConvertProjectDialog.java index e59d2d566698..cf73dba84a3a 100644 --- a/platform/lang-impl/src/com/intellij/conversion/impl/ui/ConvertProjectDialog.java +++ b/platform/lang-impl/src/com/intellij/conversion/impl/ui/ConvertProjectDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -106,10 +106,8 @@ public class ConvertProjectDialog extends DialogWrapper { final List<File> nonexistentFiles = myContext.getNonExistingModuleFiles(); if (!nonexistentFiles.isEmpty() && !myNonExistingFilesMessageShown) { final String filesString = getFilesString(nonexistentFiles); - final int res = Messages.showYesNoDialog(getContentPane(), IdeBundle.message("message.files.doesn.t.exists.0.so.the.corresponding.modules.won.t.be.converted.do.you.want.to.continue", - filesString), - IdeBundle.message("dialog.title.convert.project"), - Messages.getQuestionIcon()); + final String message = IdeBundle.message("message.text.files.do.not.exist", filesString); + final int res = Messages.showYesNoDialog(getContentPane(), message, IdeBundle.message("dialog.title.convert.project"), Messages.getQuestionIcon()); if (res != Messages.YES) { super.doOKAction(); return; diff --git a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java index a4764dae0036..0c11e71e5886 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java @@ -30,6 +30,7 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.idea.ActionsBundle; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.ListPopupStep; @@ -919,35 +920,77 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider { } } - public static ItemWrapper[] createSettingsList(@NotNull final Project project, @NotNull ExecutorProvider executorProvider, boolean createEditAction) { - final RunManagerEx manager = RunManagerEx.getInstanceEx(project); + public static ItemWrapper[] createSettingsList(@NotNull Project project, @NotNull ExecutorProvider executorProvider, boolean createEditAction) { + List<ItemWrapper> result = new ArrayList<ItemWrapper>(); - final List<ItemWrapper> result = new ArrayList<ItemWrapper>(); + if (createEditAction) { + ItemWrapper<Void> edit = new ItemWrapper<Void>(null) { + @Override + public Icon getIcon() { + return AllIcons.Actions.EditSource; + } - final RunnerAndConfigurationSettings selectedConfiguration = manager.getSelectedConfiguration(); + @Override + public String getText() { + return UIUtil.removeMnemonic(ActionsBundle.message("action.editRunConfigurations.text")); + } + @Override + public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) { + if (new EditConfigurationsDialog(project) { + @Override + protected void init() { + setOKButtonText(executor.getStartActionText()); + setOKButtonIcon(executor.getIcon()); + myExecutor = executor; + super.init(); + } + }.showAndGet()) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + RunnerAndConfigurationSettings configuration = RunManager.getInstance(project).getSelectedConfiguration(); + if (configuration != null) { + ExecutionUtil.runConfiguration(configuration, executor); + } + } + }, project.getDisposed()); + } + } + + @Override + public boolean available(Executor executor) { + return true; + } + }; + edit.setMnemonic(0); + result.add(edit); + } + + RunManagerEx manager = RunManagerEx.getInstanceEx(project); + final RunnerAndConfigurationSettings selectedConfiguration = manager.getSelectedConfiguration(); if (selectedConfiguration != null) { boolean isFirst = true; final ExecutionTarget activeTarget = ExecutionTargetManager.getActiveTarget(project); - for (final ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selectedConfiguration)) { + for (ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selectedConfiguration)) { result.add(new ItemWrapper<ExecutionTarget>(eachTarget, isFirst) { { - setChecked(eachTarget.equals(activeTarget)); + setChecked(getValue().equals(activeTarget)); } @Override public Icon getIcon() { - return eachTarget.getIcon(); + return getValue().getIcon(); } @Override public String getText() { - return eachTarget.getDisplayName(); + return getValue().getDisplayName(); } @Override public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) { - ExecutionTargetManager.setActiveTarget(project, eachTarget); + ExecutionTargetManager.setActiveTarget(project, getValue()); ExecutionUtil.runConfiguration(selectedConfiguration, executor); } @@ -960,18 +1003,24 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider { } } - final Map<RunnerAndConfigurationSettings, ItemWrapper> wrappedExisting = new LinkedHashMap<RunnerAndConfigurationSettings, ItemWrapper>(); - final ConfigurationType[] types = manager.getConfigurationFactories(); - for (final ConfigurationType type : types) { + Map<RunnerAndConfigurationSettings, ItemWrapper> wrappedExisting = new LinkedHashMap<RunnerAndConfigurationSettings, ItemWrapper>(); + for (ConfigurationType type : manager.getConfigurationFactories()) { if (!(type instanceof UnknownConfigurationType)) { Map<String, List<RunnerAndConfigurationSettings>> structure = manager.getStructure(type); - for (final Map.Entry<String, List<RunnerAndConfigurationSettings>> entry : structure.entrySet()) { - if (entry.getValue().isEmpty()) + for (Map.Entry<String, List<RunnerAndConfigurationSettings>> entry : structure.entrySet()) { + if (entry.getValue().isEmpty()) { continue; + } + final String key = entry.getKey(); - if (key != null){ + if (key != null) { boolean isSelected = entry.getValue().contains(selectedConfiguration); - FolderWrapper folderWrapper = new FolderWrapper(project, executorProvider, key + (isSelected ? " (mnemonic is to \"" + selectedConfiguration.getName()+"\")" : ""), entry.getValue()); + if (isSelected) { + assert selectedConfiguration != null; + } + FolderWrapper folderWrapper = new FolderWrapper(project, executorProvider, + key + (isSelected ? " (mnemonic is to \"" + selectedConfiguration.getName() + "\")" : ""), + entry.getValue()); if (isSelected) { folderWrapper.setMnemonic(1); } @@ -992,53 +1041,6 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider { populateWithDynamicRunners(result, wrappedExisting, project, manager, selectedConfiguration); result.addAll(wrappedExisting.values()); - - //noinspection unchecked - final ItemWrapper edit = new ItemWrapper(null) { - @Override - public Icon getIcon() { - return AllIcons.Actions.EditSource; - } - - @Override - public String getText() { - return UIUtil.removeMnemonic(ActionsBundle.message("action.editRunConfigurations.text")); - } - - @Override - public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) { - final EditConfigurationsDialog dialog = new EditConfigurationsDialog(project) { - @Override - protected void init() { - setOKButtonText(executor.getStartActionText()); - setOKButtonIcon(executor.getIcon()); - myExecutor = executor; - super.init(); - } - }; - - dialog.show(); - if (dialog.isOK()) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - ExecutionUtil.runConfiguration(RunManager.getInstance(project).getSelectedConfiguration(), executor); - } - }); - } - } - - @Override - public boolean available(Executor executor) { - return true; - } - }; - - edit.setMnemonic(0); - if (createEditAction) { - result.add(0, edit); - } - return result.toArray(new ItemWrapper[result.size()]); } diff --git a/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesComponent.java b/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesComponent.java new file mode 100644 index 000000000000..4375e164fed4 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesComponent.java @@ -0,0 +1,142 @@ +/* + * Copyright 2000-2012 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. + */ + +/* + * User: anna + * Date: 14-May-2007 + */ +package com.intellij.execution.configuration; + +import com.intellij.execution.ExecutionBundle; +import com.intellij.openapi.ui.LabeledComponent; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.util.Comparing; +import com.intellij.ui.UserActivityProviderComponent; +import com.intellij.util.ArrayUtil; +import com.intellij.util.EnvironmentUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import javax.swing.event.ChangeListener; +import java.io.File; +import java.util.Map; + +public class EnvironmentVariablesComponent extends LabeledComponent<TextFieldWithBrowseButton> implements UserActivityProviderComponent { + @NonNls private static final String ENVS = "envs"; + @NonNls public static final String ENV = "env"; + @NonNls public static final String NAME = "name"; + @NonNls public static final String VALUE = "value"; + @NonNls private static final String OPTION = "option"; + @NonNls private static final String ENV_VARIABLES = "ENV_VARIABLES"; + + private final EnvironmentVariablesTextFieldWithBrowseButton myEnvVars; + + public EnvironmentVariablesComponent() { + super(); + myEnvVars = new EnvironmentVariablesTextFieldWithBrowseButton(); + setComponent(myEnvVars); + setText(ExecutionBundle.message("environment.variables.component.title")); + } + + public void setEnvs(@NotNull Map<String, String> envs) { + myEnvVars.setEnvs(envs); + } + + @NotNull + public Map<String, String> getEnvs() { + return myEnvVars.getEnvs(); + } + + public boolean isPassParentEnvs() { + return myEnvVars.isPassParentEnvs(); + } + + public void setPassParentEnvs(final boolean passParentEnvs) { + myEnvVars.setPassParentEnvs(passParentEnvs); + } + + public static void readExternal(Element element, Map<String, String> envs) { + final Element envsElement = element.getChild(ENVS); + if (envsElement != null) { + for (Object o : envsElement.getChildren(ENV)) { + Element envElement = (Element)o; + final String envName = envElement.getAttributeValue(NAME); + final String envValue = envElement.getAttributeValue(VALUE); + if (envName != null && envValue != null) { + envs.put(envName, envValue); + } + } + } else { //compatibility with prev version + for (Object o : element.getChildren(OPTION)) { + if (Comparing.strEqual(((Element)o).getAttributeValue(NAME), ENV_VARIABLES)) { + splitVars(envs, ((Element)o).getAttributeValue(VALUE)); + break; + } + } + } + } + + private static void splitVars(final Map<String, String> envs, final String val) { + if (val != null) { + final String[] envVars = val.split(";"); + for (String envVar : envVars) { + final int idx = envVar.indexOf('='); + if (idx > -1) { + envs.put(envVar.substring(0, idx), idx < envVar.length() - 1 ? envVar.substring(idx + 1) : ""); + } + } + } + } + + public static void writeExternal(Element element, Map<String, String> envs) { + final Element envsElement = new Element(ENVS); + for (String envName : envs.keySet()) { + final Element envElement = new Element(ENV); + envElement.setAttribute(NAME, envName); + envElement.setAttribute(VALUE, envs.get(envName)); + envsElement.addContent(envElement); + } + element.addContent(envsElement); + } + + /** + * To be removed in IDEA 15 + * @deprecated use {@link com.intellij.util.EnvironmentUtil#inlineParentOccurrences(java.util.Map)} instead + */ + @Deprecated + public static void inlineParentOccurrences(final Map<String, String> envs) { + EnvironmentUtil.inlineParentOccurrences(envs); + } + + /** + * To be removed in IDEA 15 + */ + @Deprecated + public static boolean containsEnvKeySubstitution(final String envKey, final String val) { + return ArrayUtil.find(val.split(File.pathSeparator), "$" + envKey + "$") != -1; + } + + @Override + public void addChangeListener(final ChangeListener changeListener) { + myEnvVars.addChangeListener(changeListener); + } + + @Override + public void removeChangeListener(final ChangeListener changeListener) { + myEnvVars.removeChangeListener(changeListener); + } +} diff --git a/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesTextFieldWithBrowseButton.java b/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesTextFieldWithBrowseButton.java new file mode 100644 index 000000000000..5f3785f1de66 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesTextFieldWithBrowseButton.java @@ -0,0 +1,158 @@ +/* + * 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. + * 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.execution.configuration; + +import com.google.common.collect.ImmutableMap; +import com.intellij.execution.ExecutionBundle; +import com.intellij.execution.util.EnvVariablesTable; +import com.intellij.execution.util.EnvironmentVariable; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.ui.UserActivityProviderComponent; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class EnvironmentVariablesTextFieldWithBrowseButton extends TextFieldWithBrowseButton implements UserActivityProviderComponent { + + private Map<String, String> myEnvs = Collections.emptyMap(); + private boolean myPassParentEnvs; + private final List<ChangeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); + + public EnvironmentVariablesTextFieldWithBrowseButton() { + super(); + setEditable(false); + addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + new MyEnvironmentVariablesDialog().show(); + } + }); + } + + /** + * @return unmodifiable Map instance, use {@link #setEnvs(java.util.Map)} to update env vars + */ + @NotNull + public Map<String, String> getEnvs() { + return myEnvs; + } + + /** + * @param envs Map instance with reliable user-specified iteration order, + * like {@link java.util.LinkedHashMap} or {@link com.google.common.collect.ImmutableMap} + */ + public void setEnvs(@NotNull Map<String, String> envs) { + myEnvs = ImmutableMap.copyOf(envs); + String envsStr = stringifyEnvs(myEnvs); + setText(envsStr); + } + + @NotNull + private static String stringifyEnvs(@NotNull Map<String, String> envs) { + if (envs.isEmpty()) { + return ""; + } + StringBuilder buf = new StringBuilder(); + for (Map.Entry<String, String> entry : envs.entrySet()) { + if (buf.length() > 0) { + buf.append(";"); + } + buf.append(entry.getKey()).append("=").append(entry.getValue()); + } + return buf.toString(); + } + + public boolean isPassParentEnvs() { + return myPassParentEnvs; + } + + public void setPassParentEnvs(boolean passParentEnvs) { + if (myPassParentEnvs != passParentEnvs) { + myPassParentEnvs = passParentEnvs; + fireStateChanged(); + } + } + + @Override + public void addChangeListener(ChangeListener changeListener) { + myListeners.add(changeListener); + } + + @Override + public void removeChangeListener(ChangeListener changeListener) { + myListeners.remove(changeListener); + } + + private void fireStateChanged() { + for (ChangeListener listener : myListeners) { + listener.stateChanged(new ChangeEvent(this)); + } + } + + private class MyEnvironmentVariablesDialog extends DialogWrapper { + private final EnvVariablesTable myEnvVariablesTable; + private final JCheckBox myUseDefaultCb = new JCheckBox(ExecutionBundle.message("env.vars.checkbox.title")); + private final JPanel myWholePanel = new JPanel(new BorderLayout()); + + protected MyEnvironmentVariablesDialog() { + super(EnvironmentVariablesTextFieldWithBrowseButton.this, true); + myEnvVariablesTable = new EnvVariablesTable(); + List<EnvironmentVariable> envVariables = ContainerUtil.map(myEnvs.entrySet(), new Function<Map.Entry<String, String>, EnvironmentVariable>() { + @Override + public EnvironmentVariable fun(Map.Entry<String, String> entry) { + return new EnvironmentVariable(entry.getKey(), entry.getValue(), false); + } + }); + myEnvVariablesTable.setValues(envVariables); + myUseDefaultCb.setSelected(isPassParentEnvs()); + myWholePanel.add(myEnvVariablesTable.getComponent(), BorderLayout.CENTER); + myWholePanel.add(myUseDefaultCb, BorderLayout.SOUTH); + setTitle(ExecutionBundle.message("environment.variables.dialog.title")); + init(); + } + + @Override + @Nullable + protected JComponent createCenterPanel() { + return myWholePanel; + } + + @Override + protected void doOKAction() { + myEnvVariablesTable.stopEditing(); + final Map<String, String> envs = new LinkedHashMap<String, String>(); + for (EnvironmentVariable variable : myEnvVariablesTable.getEnvironmentVariables()) { + envs.put(variable.getName(), variable.getValue()); + } + setEnvs(envs); + setPassParentEnvs(myUseDefaultCb.isSelected()); + super.doOKAction(); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index 605d073945b5..3fce510e725e 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -674,7 +674,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo final Document document = myEditor.getDocument(); final RangeMarker lastProcessedOutput = document.createRangeMarker(document.getTextLength(), document.getTextLength()); final int caretOffset = myEditor.getCaretModel().getOffset(); - final boolean isAtLastLine = document.getLineNumber(caretOffset) >= document.getLineCount() - 1; + final boolean isAtLastLine = isCaretAtLastLine(); CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { @Override @@ -1078,6 +1078,9 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo }; if (immediately) { model.runBatchFoldingOperation(operation); + if (isCaretAtLastLine()) { + EditorUtil.scrollToTheEnd(myEditor); + } } else { model.runBatchFoldingOperationDoNotCollapseCaret(operation); @@ -1092,6 +1095,12 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo } } + private boolean isCaretAtLastLine() { + final Document document = myEditor.getDocument(); + final int caretOffset = myEditor.getCaretModel().getOffset(); + return document.getLineNumber(caretOffset) >= document.getLineCount() - 1; + } + private void addFolding(Document document, CharSequence chars, int line, List<FoldRegion> toAdd) { String commandLinePlaceholder = myCommandLineFolding.getPlaceholder(line); if (commandLinePlaceholder != null) { diff --git a/platform/lang-impl/src/com/intellij/execution/impl/EditConfigurationsDialog.java b/platform/lang-impl/src/com/intellij/execution/impl/EditConfigurationsDialog.java index d206283375e2..265d9c3f7410 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/EditConfigurationsDialog.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/EditConfigurationsDialog.java @@ -26,7 +26,7 @@ public class EditConfigurationsDialog extends SingleConfigurableEditor implement protected Executor myExecutor; public EditConfigurationsDialog(final Project project) { - super(project, new RunConfigurable(project), IdeModalityType.PROJECT); + super(project, new RunConfigurable(project), "#com.intellij.execution.impl.EditConfigurationsDialog", IdeModalityType.PROJECT); ((RunConfigurable)getConfigurable()).setRunDialog(this); setTitle(ExecutionBundle.message("run.debug.dialog.title")); setHorizontalStretch(1.3F); @@ -42,11 +42,6 @@ public class EditConfigurationsDialog extends SingleConfigurableEditor implement } } - @Override - protected String getDimensionServiceKey() { - return "#com.intellij.execution.impl.EditConfigurationsDialog"; - } - @Nullable @Override public Executor getExecutor() { diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java index 3645439db470..95d4db09c297 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java @@ -589,8 +589,14 @@ class RunConfigurable extends BaseConfigurable { @Override public JComponent createComponent() { for (RunConfigurationsSettings each : Extensions.getExtensions(RunConfigurationsSettings.EXTENSION_POINT)) { - UnnamedConfigurable configurable = each.createConfigurable(); - myAdditionalSettings.add(Pair.create(configurable, configurable.createComponent())); + try { + UnnamedConfigurable configurable = each.createConfigurable(myProject); + myAdditionalSettings.add(Pair.create(configurable, configurable.createComponent())); + } + catch (NoSuchMethodError e) { + // in case someone has already implemented old RunConfigurationsSettings.createConfigurable() + LOG.error(e); + } } myWholePanel = new JPanel(new BorderLayout()); diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java index 7bcabebf256a..d1c3c4877493 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java @@ -104,6 +104,13 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole myConsoleView.attachToProcess(myProcessHandler); // Runner creating + createContentDescriptorAndActions(); + + // Run + myProcessHandler.startNotify(); + } + + protected void createContentDescriptorAndActions() { final Executor defaultExecutor = DefaultRunExecutor.getRunExecutorInstance(); final DefaultActionGroup toolbarActions = new DefaultActionGroup(); final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions, false); @@ -134,9 +141,6 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole panel.updateUI(); showConsole(defaultExecutor, contentDescriptor); - - // Run - myProcessHandler.startNotify(); } protected String constructConsoleTitle(final @NotNull String consoleTitle) { diff --git a/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java b/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java index 5f7321aa8068..f4cae36d1ffe 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java @@ -21,25 +21,19 @@ import com.intellij.execution.ExecutionResult; import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; /** * @author spleaner */ public abstract class DefaultProgramRunner extends GenericProgramRunner { - @Override - protected RunContentDescriptor doExecute(@NotNull final Project project, - @NotNull final RunProfileState state, - final RunContentDescriptor contentToReuse, - @NotNull final ExecutionEnvironment env) throws ExecutionException { + protected RunContentDescriptor doExecute(@NotNull RunProfileState state, @NotNull ExecutionEnvironment env) throws ExecutionException { FileDocumentManager.getInstance().saveAllDocuments(); ExecutionResult executionResult = state.execute(env.getExecutor(), this); if (executionResult == null) { return null; } - return new RunContentBuilder(executionResult, env).showRunContent(contentToReuse); + return new RunContentBuilder(executionResult, env).showRunContent(env.getContentToReuse()); } - } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index b8225b0c238b..5384ea06de23 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -290,7 +290,8 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac final ContentManager manager = ContentFactory.SERVICE.getInstance().createContentManager(this, false, myProject); Disposer.register((Disposable)myRunnerUi, manager); manager.getComponent(); - } else { + } + else { final DockManager dockManager = DockManager.getInstance(myProject); if (dockManager != null) { //default project dockManager.register(this); @@ -518,13 +519,15 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac @Override public void closeAll() { final Content[] contents = myManager.getContents(); - for (Content content : contents) { - getStateFor(content).setWindow(0); - } if (myOriginal != null) { for (Content content : contents) { + getStateFor(content).setWindow(0); myOriginal.myManager.addContent(content); - myOriginal.findCellFor(content).minimize(content); + GridCell cell = myOriginal.findCellFor(content); + if (cell != null) { + myOriginal.restoreContent(content.getUserData(ViewImpl.ID)); + cell.minimize(content); + } } } myManager.removeAllContents(false); @@ -1373,7 +1376,6 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } private class MyComponent extends Wrapper.FocusHolder implements DataProvider, QuickActionProvider { - private boolean myWasEverAdded; public MyComponent() { @@ -1388,9 +1390,13 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac if (KEY.is(dataId)) { return RunnerContentUi.this; } - else { - return null; + + ContentManager originalContentManager = myOriginal == null ? null : myOriginal.getContentManager(); + JComponent originalContentComponent = originalContentManager == null ? null : originalContentManager.getComponent(); + if (originalContentComponent instanceof DataProvider) { + return ((DataProvider)originalContentComponent).getData(dataId); } + return null; } @SuppressWarnings("NullableProblems") @@ -1839,9 +1845,6 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac public void dragOutFinished(MouseEvent event, TabInfo source) { final Component component = event.getComponent(); final IdeFrame window = UIUtil.getParentOfType(IdeFrame.class, component); - if (window != null) { - - } mySession.process(event); mySession = null; } diff --git a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java index 84776f4bf7ff..98975c8529dc 100644 --- a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java +++ b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java @@ -45,6 +45,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.pom.Navigatable; @@ -859,7 +860,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction { } data.addAll(visibleNodes); if (data.isEmpty()) { - String progressText = UsageViewManagerImpl.getProgressTitle(presentation); + String progressText = StringUtil.escapeXml(UsageViewManagerImpl.getProgressTitle(presentation)); data.add(createStringNode(progressText)); } Collections.sort(data, USAGE_NODE_COMPARATOR); diff --git a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java index b78ce2c7ead7..87d0b78acf39 100644 --- a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java +++ b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java @@ -52,14 +52,14 @@ public class FindInProjectManager { public void findInProject(@NotNull DataContext dataContext) { final boolean isOpenInNewTabEnabled; - final boolean[] toOpenInNewTab = new boolean[1]; + final boolean toOpenInNewTab; Content selectedContent = UsageViewManager.getInstance(myProject).getSelectedContent(true); if (selectedContent != null && selectedContent.isPinned()) { - toOpenInNewTab[0] = true; + toOpenInNewTab = true; isOpenInNewTabEnabled = false; } else { - toOpenInNewTab[0] = FindSettings.getInstance().isShowResultsInSeparateView(); + toOpenInNewTab = FindSettings.getInstance().isShowResultsInSeparateView(); isOpenInNewTabEnabled = UsageViewManager.getInstance(myProject).getReusableContentsCount() > 0; } @@ -68,7 +68,7 @@ public class FindInProjectManager { findModel.setReplaceState(false); findModel.setOpenInNewTabVisible(true); findModel.setOpenInNewTabEnabled(isOpenInNewTabEnabled); - findModel.setOpenInNewTab(toOpenInNewTab[0]); + findModel.setOpenInNewTab(toOpenInNewTab); FindInProjectUtil.setDirectoryName(findModel, dataContext); String text = PlatformDataKeys.PREDEFINED_TEXT.getData(dataContext); @@ -85,7 +85,7 @@ public class FindInProjectManager { public void run() { findModel.setOpenInNewTabVisible(false); if (isOpenInNewTabEnabled) { - FindSettings.getInstance().setShowResultsInSeparateView(toOpenInNewTab[0] = findModel.isOpenInNewTab()); + FindSettings.getInstance().setShowResultsInSeparateView(findModel.isOpenInNewTab()); } startFindInProject(findModel); diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java index 7e9e71d7a94d..7dfdbbce16d7 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java @@ -421,7 +421,7 @@ class FindInProjectTask { SearchScope customScope = myFindModel.getCustomScope(); GlobalSearchScope scope = myPsiDirectory != null - ? GlobalSearchScopesCore.directoryScope(myPsiDirectory, true) + ? GlobalSearchScopesCore.directoryScope(myPsiDirectory, myFindModel.isWithSubdirectories()) : myModule != null ? myModule.getModuleContentScope() : customScope instanceof GlobalSearchScope diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java index 4ba97e0151e5..995a67ecafa1 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java @@ -21,7 +21,10 @@ import com.intellij.find.FindModel; import com.intellij.find.FindResult; import com.intellij.ide.IdeTooltipManager; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.event.*; @@ -46,7 +49,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; -import java.io.*; +import java.io.PrintStream; import java.util.*; import java.util.List; @@ -95,11 +98,8 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search private RangeHighlighter myCursorHighlighter; private final List<VisibleAreaListener> myVisibleAreaListenersToRemove = new ArrayList<VisibleAreaListener>(); - private static TextAttributes strikout(TextAttributes attributes) { - TextAttributes textAttributes = attributes.clone(); - textAttributes.setEffectColor(Color.BLACK); - textAttributes.setEffectType(EffectType.STRIKEOUT); - return textAttributes; + private static TextAttributes strikout() { + return EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.DEPRECATED_ATTRIBUTES).clone(); } private Delegate myDelegate; @@ -161,7 +161,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search ranges.add(new Pair<Integer, Character>(editor.getDocument().getTextLength()+1, '\n')); ContainerUtil.sort(ranges, new Comparator<Pair<Integer, Character>>() { @Override - public int compare(Pair<Integer, Character> pair, Pair<Integer, Character> pair2) { + public int compare(@NotNull Pair<Integer, Character> pair, @NotNull Pair<Integer, Character> pair2) { int res = pair.first - pair2.first; if (res == 0) { @@ -210,7 +210,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search } myHighlighters.removeAll(unused); Project project = mySearchResults.getProject(); - if (!project.isDisposed()) { + if (project != null && !project.isDisposed()) { for (RangeHighlighter highlighter : unused) { HighlightManager.getInstance(project).removeSegmentHighlighter(mySearchResults.getEditor(), highlighter); } @@ -240,7 +240,8 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search Editor editor = mySearchResults.getEditor(); if (cursor != null) { Set<RangeHighlighter> dummy = new HashSet<RangeHighlighter>(); - highlightRange(cursor, new TextAttributes(null, null, Color.BLACK, EffectType.ROUNDED_BOX, 0), dummy); + Color color = editor.getColorsScheme().getColor(EditorColors.CARET_COLOR); + highlightRange(cursor, new TextAttributes(null, null, color, EffectType.ROUNDED_BOX, 0), dummy); if (!dummy.isEmpty()) { myCursorHighlighter = dummy.iterator().next(); } @@ -322,7 +323,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search attributes.setEffectColor(attributes.getBackgroundColor()); } if (mySearchResults.isExcluded(range)) { - highlightRange(range, strikout(attributes), myHighlighters); + highlightRange(range, strikout(), myHighlighters); } else { highlightRange(range, attributes, myHighlighters); } @@ -389,18 +390,18 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search final FindModel findModel = mySearchResults.getFindModel(); if (findModel.isRegularExpressions() && findModel.isReplaceState()) { - showBalloon(cursor, editor, replacementPreviewText); + showBalloon(editor, replacementPreviewText); } } } - private void showBalloon(FindResult cursor, Editor editor, String replacementPreviewText) { + private void showBalloon(Editor editor, String replacementPreviewText) { if (ApplicationManager.getApplication().isUnitTestMode()) { myReplacementPreviewText = replacementPreviewText; return; } - ReplacementView replacementView = new ReplacementView(replacementPreviewText, cursor); + ReplacementView replacementView = new ReplacementView(replacementPreviewText); BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().createBalloonBuilder(replacementView); balloonBuilder.setFadeoutTime(0); @@ -546,7 +547,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search } } - private void requestBalloonHiding(final Balloon object) { + private static void requestBalloonHiding(final Balloon object) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/ReplacementView.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/ReplacementView.java index 4f87efd8c970..b9b01667a656 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/ReplacementView.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/ReplacementView.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 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. @@ -15,30 +15,28 @@ */ package com.intellij.find.impl.livePreview; -import com.intellij.find.FindResult; +import com.intellij.ui.Gray; import com.intellij.ui.JBColor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; public class ReplacementView extends JPanel { - private static final String MALFORMED_REPLACEMENT_STRING = "Malformed replacement string"; - private final String myReplacement; @Override - protected void paintComponent(Graphics graphics) { - + protected void paintComponent(@NotNull Graphics graphics) { } - public ReplacementView(final String replacement, final FindResult occurrence) { - myReplacement = replacement; - String textToShow = myReplacement; - if (myReplacement == null) { + public ReplacementView(@Nullable String replacement) { + String textToShow = replacement; + if (replacement == null) { textToShow = MALFORMED_REPLACEMENT_STRING; } JLabel jLabel = new JLabel(textToShow); - jLabel.setForeground(myReplacement != null ? Color.WHITE : JBColor.RED); + jLabel.setForeground(replacement != null ? new JBColor(Gray._240, Gray._200) : JBColor.RED); add(jLabel); } } diff --git a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java index 7e220c149369..0c6a3766342d 100644 --- a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java +++ b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java @@ -20,6 +20,7 @@ import com.intellij.find.*; import com.intellij.find.actions.FindInPathAction; import com.intellij.find.findInProject.FindInProjectManager; import com.intellij.find.impl.FindInProjectUtil; +import com.intellij.find.impl.FindManagerImpl; import com.intellij.ide.DataManager; import com.intellij.notification.NotificationGroup; import com.intellij.openapi.actionSystem.ActionManager; @@ -38,6 +39,7 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Segment; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -48,9 +50,8 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.ui.content.Content; -import com.intellij.usageView.*; +import com.intellij.usageView.UsageInfo; import com.intellij.usages.*; -import com.intellij.usages.UsageViewManager; import com.intellij.usages.impl.UsageViewImpl; import com.intellij.usages.rules.UsageInFile; import com.intellij.util.AdapterProcessor; @@ -115,9 +116,23 @@ public class ReplaceInProjectManager { } public void replaceInProject(@NotNull DataContext dataContext) { + final boolean isOpenInNewTabEnabled; + final boolean toOpenInNewTab; + final Content selectedContent = com.intellij.usageView.UsageViewManager.getInstance(myProject).getSelectedContent(true); + if (selectedContent != null && selectedContent.isPinned()) { + toOpenInNewTab = true; + isOpenInNewTabEnabled = false; + } + else { + toOpenInNewTab = FindSettings.getInstance().isShowResultsInSeparateView(); + isOpenInNewTabEnabled = com.intellij.usageView.UsageViewManager.getInstance(myProject).getReusableContentsCount() > 0; + } final FindManager findManager = FindManager.getInstance(myProject); - final FindModel findModel = (FindModel)findManager.getFindInProjectModel().clone(); + final FindModel findModel = findManager.getFindInProjectModel().clone(); findModel.setReplaceState(true); + findModel.setOpenInNewTabVisible(true); + findModel.setOpenInNewTabEnabled(isOpenInNewTabEnabled); + findModel.setOpenInNewTab(toOpenInNewTab); FindInProjectUtil.setDirectoryName(findModel, dataContext); Editor editor = CommonDataKeys.EDITOR.getData(dataContext); @@ -138,9 +153,9 @@ public class ReplaceInProjectManager { if (manager == null) return; findManager.getFindInProjectModel().copyFrom(findModel); - final FindModel findModelCopy = (FindModel)findModel.clone(); + final FindModel findModelCopy = findModel.clone(); - final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(true, findModelCopy); + final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(findModel.isOpenInNewTab(), findModelCopy); final FindUsagesProcessPresentation processPresentation = FindInProjectUtil.setupProcessPresentation(myProject, true, presentation); UsageSearcherFactory factory = new UsageSearcherFactory(findModelCopy, psiDirectory, processPresentation); @@ -168,7 +183,7 @@ public class ReplaceInProjectManager { @Override public String getLongDescriptiveName() { UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(false, myFindModel); - return "Replace "+presentation.getToolwindowTitle()+" with '"+ myFindModel.getStringToReplace()+"'"; + return "Replace "+ StringUtil.decapitalize(presentation.getToolwindowTitle())+" with '"+ myFindModel.getStringToReplace()+"'"; } @Override @@ -193,7 +208,9 @@ public class ReplaceInProjectManager { final FindManager findManager) { presentation.setMergeDupLinesAvailable(false); final ReplaceContext[] context = new ReplaceContext[1]; - manager.searchAndShowUsages(new UsageTarget[]{new ReplaceInProjectTarget(myProject, findModelCopy)}, + final ReplaceInProjectTarget target = new ReplaceInProjectTarget(myProject, findModelCopy); + ((FindManagerImpl)FindManager.getInstance(myProject)).getFindUsagesManager().addToHistory(target); + manager.searchAndShowUsages(new UsageTarget[]{target}, usageSearcherFactory, processPresentation, presentation, new UsageViewManager.UsageViewStateListener() { @Override public void usageViewCreated(@NotNull UsageView usageView) { diff --git a/platform/lang-impl/src/com/intellij/formatting/alignment/AlignmentStrategy.java b/platform/lang-impl/src/com/intellij/formatting/alignment/AlignmentStrategy.java index 1844a0a217d2..0be9a469a03e 100644 --- a/platform/lang-impl/src/com/intellij/formatting/alignment/AlignmentStrategy.java +++ b/platform/lang-impl/src/com/intellij/formatting/alignment/AlignmentStrategy.java @@ -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. @@ -69,8 +69,7 @@ public abstract class AlignmentStrategy { * @return alignment strategy for the given arguments */ public static AlignmentPerTypeStrategy createAlignmentPerTypeStrategy(@NotNull Collection<IElementType> targetTypes, - boolean allowBackwardShift) - { + boolean allowBackwardShift) { return new AlignmentPerTypeStrategy(targetTypes, null, allowBackwardShift, Alignment.Anchor.LEFT); } @@ -85,8 +84,7 @@ public abstract class AlignmentStrategy { * @return alignment retrieval strategy that follows the rules described above */ public static AlignmentPerTypeStrategy createAlignmentPerTypeStrategy( - @NotNull Collection<IElementType> targetTypes, @Nullable IElementType parentType, boolean allowBackwardShift) - { + @NotNull Collection<IElementType> targetTypes, @Nullable IElementType parentType, boolean allowBackwardShift) { return createAlignmentPerTypeStrategy(targetTypes, parentType, allowBackwardShift, Alignment.Anchor.LEFT); } @@ -115,8 +113,7 @@ public abstract class AlignmentStrategy { */ public static AlignmentPerTypeStrategy createAlignmentPerTypeStrategy( @NotNull Collection<IElementType> targetTypes, @Nullable IElementType parentType, boolean allowBackwardShift, - @NotNull Alignment.Anchor anchor) - { + @NotNull Alignment.Anchor anchor) { return new AlignmentPerTypeStrategy(targetTypes, parentType, allowBackwardShift, anchor); } @@ -162,7 +159,7 @@ public abstract class AlignmentStrategy { @Override @Nullable public Alignment getAlignment(@Nullable IElementType parentType, @Nullable IElementType childType) { - return (myFilterElementTypes.contains(childType) ^ myIgnoreFilterTypes) ? myAlignment : null; + return myFilterElementTypes.contains(childType) ^ myIgnoreFilterTypes ? myAlignment : null; } } @@ -171,7 +168,6 @@ public abstract class AlignmentStrategy { * same types. */ public static class AlignmentPerTypeStrategy extends AlignmentStrategy { - private final Map<IElementType, Alignment> myAlignments = new HashMap<IElementType, Alignment>(); private final IElementType myParentType; @@ -180,8 +176,7 @@ public abstract class AlignmentStrategy { AlignmentPerTypeStrategy(Collection<IElementType> targetElementTypes, IElementType parentType, boolean allowBackwardShift, - Alignment.Anchor anchor) - { + Alignment.Anchor anchor) { myParentType = parentType; myAllowBackwardShift = allowBackwardShift; for (IElementType elementType : targetElementTypes) { diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/ExportableFileTemplateSettings.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/ExportableFileTemplateSettings.java index b601f0542dab..29cf1b18644a 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/ExportableFileTemplateSettings.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/ExportableFileTemplateSettings.java @@ -40,7 +40,6 @@ import java.util.Locale; )} ) public class ExportableFileTemplateSettings extends FileTemplatesLoader implements PersistentStateComponent<Element>, ExportableComponent { - public final static String EXPORTABLE_SETTINGS_FILE = "file.template.settings.xml"; static final String ELEMENT_TEMPLATE = "template"; @@ -58,7 +57,6 @@ public class ExportableFileTemplateSettings extends FileTemplatesLoader implemen return ServiceManager.getService(ExportableFileTemplateSettings.class); } - @NotNull @Override public File[] getExportFiles() { @@ -76,10 +74,9 @@ public class ExportableFileTemplateSettings extends FileTemplatesLoader implemen @Nullable @Override public Element getState() { - Element element = new Element("fileTemplateSettings"); + Element element = null; for (FTManager manager : getAllManagers()) { - final Element templatesGroup = new Element(getXmlElementGroupName(manager)); - element.addContent(templatesGroup); + Element templatesGroup = null; for (FileTemplateBase template : manager.getAllTemplates(true)) { // save only those settings that differ from defaults boolean shouldSave = template.isReformatCode() != FileTemplateBase.DEFAULT_REFORMAT_CODE_VALUE; @@ -95,6 +92,14 @@ public class ExportableFileTemplateSettings extends FileTemplatesLoader implemen if (template instanceof BundledFileTemplate) { templateElement.setAttribute(ATTRIBUTE_ENABLED, Boolean.toString(((BundledFileTemplate)template).isEnabled())); } + + if (templatesGroup == null) { + templatesGroup = new Element(getXmlElementGroupName(manager)); + if (element == null) { + element = new Element("fileTemplateSettings"); + } + element.addContent(templatesGroup); + } templatesGroup.addContent(templateElement); } } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateConfigurable.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateConfigurable.java index be3be30fc247..21702dc68f4f 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateConfigurable.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -21,7 +21,6 @@ import com.intellij.ide.DataManager; import com.intellij.ide.IdeBundle; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; -import com.intellij.lexer.CompositeLexer; import com.intellij.lexer.FlexAdapter; import com.intellij.lexer.Lexer; import com.intellij.lexer.MergingLexerAdapter; @@ -38,7 +37,8 @@ import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter; +import com.intellij.openapi.editor.ex.util.LayerDescriptor; +import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter; import com.intellij.openapi.editor.highlighter.EditorHighlighter; import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; import com.intellij.openapi.fileTypes.*; @@ -99,7 +99,7 @@ public class FileTemplateConfigurable implements Configurable, Configurable.NoSc private URL myDefaultDescriptionUrl; private final Project myProject; - private final List<ChangeListener> myChangeListeners = ContainerUtil.createLockFreeCopyOnWriteList();; + private final List<ChangeListener> myChangeListeners = ContainerUtil.createLockFreeCopyOnWriteList(); private Splitter mySplitter; private final FileType myVelocityFileType = FileTypeManager.getInstance().getFileTypeByExtension("ft"); private JPanel myDescriptionPanel; @@ -205,13 +205,13 @@ public class FileTemplateConfigurable implements Configurable, Configurable.NoSc myNameField.addFocusListener(new FocusAdapter() { @Override - public void focusLost(FocusEvent e) { + public void focusLost(@NotNull FocusEvent e) { onNameChanged(); } }); myExtensionField.addFocusListener(new FocusAdapter() { @Override - public void focusLost(FocusEvent e) { + public void focusLost(@NotNull FocusEvent e) { onNameChanged(); } }); @@ -221,8 +221,11 @@ public class FileTemplateConfigurable implements Configurable, Configurable.NoSc private Editor createEditor() { EditorFactory editorFactory = EditorFactory.getInstance(); - Document doc = myFile == null ? editorFactory.createDocument(myTemplate == null ? "" : myTemplate.getText()) : PsiDocumentManager.getInstance(myFile.getProject()).getDocument(myFile); - Editor editor = myProject == null ? editorFactory.createEditor(doc) : editorFactory.createEditor(doc, myProject); + Document doc = myFile == null + ? editorFactory.createDocument(myTemplate == null ? "" : myTemplate.getText()) + : PsiDocumentManager.getInstance(myFile.getProject()).getDocument(myFile); + assert doc != null; + Editor editor = editorFactory.createEditor(doc, myProject); EditorSettings editorSettings = editor.getSettings(); editorSettings.setVirtualSpace(false); @@ -367,7 +370,7 @@ public class FileTemplateConfigurable implements Configurable, Configurable.NoSc @Nullable private PsiFile createFile(final String text, final String name) { - if (myTemplate == null || myProject == null) return null; + if (myTemplate == null) return null; final FileType fileType = myVelocityFileType; if (fileType == FileTypes.UNKNOWN) return null; @@ -388,7 +391,7 @@ public class FileTemplateConfigurable implements Configurable, Configurable.NoSc } private EditorHighlighter createHighlighter() { - if (myTemplate != null && myProject != null && myVelocityFileType != FileTypes.UNKNOWN) { + if (myTemplate != null && myVelocityFileType != FileTypes.UNKNOWN) { return EditorHighlighterFactory.getInstance().createEditorHighlighter(myProject, new LightVirtualFile("aaa." + myTemplate.getExtension() + ".ft")); } @@ -399,38 +402,27 @@ public class FileTemplateConfigurable implements Configurable, Configurable.NoSc if (fileType == null) { fileType = FileTypes.PLAIN_TEXT; } + SyntaxHighlighter originalHighlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(fileType, null, null); - if (originalHighlighter == null) originalHighlighter = new PlainSyntaxHighlighter(); - return new LexerEditorHighlighter(new TemplateHighlighter(originalHighlighter), EditorColorsManager.getInstance().getGlobalScheme()); + if (originalHighlighter == null) { + originalHighlighter = new PlainSyntaxHighlighter(); + } + + final EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); + LayeredLexerEditorHighlighter highlighter = new LayeredLexerEditorHighlighter(new TemplateHighlighter(), scheme); + highlighter.registerLayer(FileTemplateTokenType.TEXT, new LayerDescriptor(originalHighlighter, "")); + return highlighter; } - private final static TokenSet TOKENS_TO_MERGE = TokenSet.create(FileTemplateTokenType.TEXT); - private static class TemplateHighlighter extends SyntaxHighlighterBase { private final Lexer myLexer; - private final SyntaxHighlighter myOriginalHighlighter; - - public TemplateHighlighter(SyntaxHighlighter original) { - myOriginalHighlighter = original; - Lexer originalLexer = original.getHighlightingLexer(); - Lexer templateLexer = new FlexAdapter(new FileTemplateTextLexer()); - templateLexer = new MergingLexerAdapter(templateLexer, TOKENS_TO_MERGE); - - myLexer = new CompositeLexer(originalLexer, templateLexer) { - @Override - protected IElementType getCompositeTokenType(IElementType type1, IElementType type2) { - if (type2 == FileTemplateTokenType.MACRO || type2 == FileTemplateTokenType.DIRECTIVE) { - return type2; - } - else { - return type1; - } - } - }; + + public TemplateHighlighter() { + myLexer = new MergingLexerAdapter(new FlexAdapter(new FileTemplateTextLexer()), TokenSet.create(FileTemplateTokenType.TEXT)); } - @Override @NotNull + @Override public Lexer getHighlightingLexer() { return myLexer; } @@ -438,14 +430,11 @@ public class FileTemplateConfigurable implements Configurable, Configurable.NoSc @Override @NotNull public TextAttributesKey[] getTokenHighlights(IElementType tokenType) { - if (tokenType == FileTemplateTokenType.MACRO) { - return pack(myOriginalHighlighter.getTokenHighlights(tokenType), TemplateColors.TEMPLATE_VARIABLE_ATTRIBUTES); - } - else if (tokenType == FileTemplateTokenType.DIRECTIVE) { - return pack(myOriginalHighlighter.getTokenHighlights(tokenType), TemplateColors.TEMPLATE_VARIABLE_ATTRIBUTES); + if (tokenType == FileTemplateTokenType.MACRO || tokenType == FileTemplateTokenType.DIRECTIVE) { + return pack(TemplateColors.TEMPLATE_VARIABLE_ATTRIBUTES); } - return myOriginalHighlighter.getTokenHighlights(tokenType); + return EMPTY; } } diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java index a27ad87f70e4..9a80f455e4e1 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java @@ -222,9 +222,8 @@ public class NavBarModel { psiElement = getOriginalElement(psiElement); PsiElement resultElement = psiElement; - for (final NavBarModelExtension modelExtension : Extensions.getExtensions(NavBarModelExtension.EP_NAME)) { - resultElement = modelExtension.adjustElement(resultElement); - } + resultElement = normalize(resultElement); + if (resultElement == null) return; boolean foundByExtension = false; for (final NavBarModelExtension modelExtension : Extensions.getExtensions(NavBarModelExtension.EP_NAME)) { @@ -326,7 +325,7 @@ public class NavBarModel { } @Nullable - private static PsiElement normalize(PsiElement child) { + private static PsiElement normalize(@Nullable PsiElement child) { if (child == null) return null; for (NavBarModelExtension modelExtension : Extensions.getExtensions(NavBarModelExtension.EP_NAME)) { child = modelExtension.adjustElement(child); diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPopup.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPopup.java index d565c69f9df4..6c0374a5d744 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPopup.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPopup.java @@ -27,6 +27,7 @@ import com.intellij.psi.PsiElement; import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBList; +import com.intellij.ui.popup.HintUpdateSupply; import com.intellij.ui.speedSearch.ListWithFilter; import com.intellij.util.Function; import com.intellij.util.NotNullFunction; @@ -92,10 +93,8 @@ public class NavBarPopup extends LightweightHint implements Disposable{ protected void onPopupCancel() { final JComponent component = getComponent(); if (component != null) { - final Object o = component.getClientProperty(JBLIST_KEY); - if (o instanceof JBListWithHintProvider) { - ((JBListWithHintProvider)o).hideHint(); - } + Object o = component.getClientProperty(JBLIST_KEY); + if (o instanceof JComponent) HintUpdateSupply.hideHint((JComponent)o); } //noinspection unchecked for (Disposable disposable : ((List<Disposable>)getList().getClientProperty(DISPOSED_OBJECTS))) { diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/ProjectViewSettings.java b/platform/lang-impl/src/com/intellij/ide/projectView/ProjectViewSettings.java new file mode 100644 index 000000000000..64e374097635 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/projectView/ProjectViewSettings.java @@ -0,0 +1,23 @@ +/* + * 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. + * 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.ide.projectView; + +/** + * @author nik + */ +public interface ProjectViewSettings extends ViewSettings { + boolean isShowExcludedFiles(); +} diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewPane.java index 52e79d208147..bc2e509e085a 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewPane.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewPane.java @@ -23,15 +23,25 @@ import com.intellij.icons.AllIcons; import com.intellij.ide.IdeBundle; import com.intellij.ide.SelectInTarget; import com.intellij.ide.impl.ProjectPaneSelectInTarget; +import com.intellij.ide.projectView.ProjectView; +import com.intellij.ide.projectView.ProjectViewSettings; import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper; import com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode; import com.intellij.ide.util.treeView.AbstractTreeBuilder; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.ide.util.treeView.AbstractTreeUpdater; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.JDOMExternalizerUtil; +import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiDirectory; +import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -42,6 +52,8 @@ import java.awt.*; public class ProjectViewPane extends AbstractProjectViewPSIPane { @NonNls public static final String ID = "ProjectPane"; + public static final String SHOW_EXCLUDED_FILES_OPTION = "show-excluded-files"; + private boolean myShowExcludedFiles = true; public ProjectViewPane(Project project) { super(project); @@ -76,12 +88,7 @@ public class ProjectViewPane extends AbstractProjectViewPSIPane { @Override protected ProjectAbstractTreeStructureBase createStructure() { - return new ProjectTreeStructure(myProject, ID){ - @Override - protected AbstractTreeNode createRoot(final Project project, ViewSettings settings) { - return new ProjectViewProjectNode(project, settings); - } - }; + return new ProjectViewPaneTreeStructure(); } @Override @@ -111,6 +118,25 @@ public class ProjectViewPane extends AbstractProjectViewPSIPane { return "ProjectPane"; } + @Override + public void readExternal(Element element) throws InvalidDataException { + super.readExternal(element); + String showExcludedOption = JDOMExternalizerUtil.readField(element, SHOW_EXCLUDED_FILES_OPTION); + myShowExcludedFiles = showExcludedOption == null || Boolean.parseBoolean(showExcludedOption); + } + + @Override + public void writeExternal(Element element) throws WriteExternalException { + super.writeExternal(element); + if (!myShowExcludedFiles) { + JDOMExternalizerUtil.writeField(element, SHOW_EXCLUDED_FILES_OPTION, String.valueOf(false)); + } + } + + @Override + public void addToolbarActions(DefaultActionGroup actionGroup) { + actionGroup.addAction(new ShowExcludedFilesAction()).setAsSecondary(true); + } // should be first @Override @@ -148,4 +174,47 @@ public class ProjectViewPane extends AbstractProjectViewPSIPane { return super.addSubtreeToUpdateByElement(element); } } + + private class ProjectViewPaneTreeStructure extends ProjectTreeStructure implements ProjectViewSettings { + public ProjectViewPaneTreeStructure() { + super(ProjectViewPane.this.myProject, ID); + } + + @Override + protected AbstractTreeNode createRoot(final Project project, ViewSettings settings) { + return new ProjectViewProjectNode(project, settings); + } + + @Override + public boolean isShowExcludedFiles() { + return myShowExcludedFiles; + } + } + + private final class ShowExcludedFilesAction extends ToggleAction { + private ShowExcludedFilesAction() { + super(IdeBundle.message("action.show.excluded.files"), IdeBundle.message("action.show.hide.excluded.files"), null); + } + + @Override + public boolean isSelected(AnActionEvent event) { + return myShowExcludedFiles; + } + + @Override + public void setSelected(AnActionEvent event, boolean flag) { + if (myShowExcludedFiles != flag) { + myShowExcludedFiles = flag; + updateFromRoot(true); + } + } + + @Override + public void update(AnActionEvent e) { + super.update(e); + final Presentation presentation = e.getPresentation(); + final ProjectView projectView = ProjectView.getInstance(myProject); + presentation.setVisible(projectView.getCurrentProjectViewPane() == ProjectViewPane.this); + } + } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java index 13ba91900521..36c09aff2218 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewDirectoryHelper.java @@ -21,6 +21,7 @@ package com.intellij.ide.projectView.impl.nodes; import com.intellij.ide.projectView.ProjectViewNode; +import com.intellij.ide.projectView.ProjectViewSettings; import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.openapi.components.ServiceManager; @@ -37,10 +38,8 @@ import com.intellij.openapi.roots.impl.DirectoryInfo; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; +import com.intellij.psi.*; +import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.util.PsiUtilCore; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; @@ -126,7 +125,7 @@ public class ProjectViewDirectoryHelper { final Module module = fileIndex.getModuleForFile(psiDirectory.getVirtualFile()); final ModuleFileIndex moduleFileIndex = module == null ? null : ModuleRootManager.getInstance(module).getFileIndex(); if (!settings.isFlattenPackages() || skipDirectory(psiDirectory)) { - processPsiDirectoryChildren(psiDirectory, directoryChildrenInProject(fileIndex, psiDirectory), + processPsiDirectoryChildren(psiDirectory, directoryChildrenInProject(psiDirectory, settings), children, fileIndex, null, settings, withSubDirectories); } else { // source directory in "flatten packages" mode @@ -172,10 +171,20 @@ public class ProjectViewDirectoryHelper { return topLevelContentRoots; } - private PsiElement[] directoryChildrenInProject(ProjectFileIndex fileIndex, PsiDirectory psiDirectory) { - VirtualFile dir = psiDirectory.getVirtualFile(); - if (isInProject(dir)) { - return psiDirectory.getChildren(); + private PsiElement[] directoryChildrenInProject(PsiDirectory psiDirectory, final ViewSettings settings) { + final VirtualFile dir = psiDirectory.getVirtualFile(); + if (shouldBeShown(dir, settings)) { + final List<PsiElement> children = new ArrayList<PsiElement>(); + psiDirectory.processChildren(new PsiElementProcessor<PsiFileSystemItem>() { + @Override + public boolean execute(@NotNull PsiFileSystemItem element) { + if (shouldBeShown(element.getVirtualFile(), settings)) { + children.add(element); + } + return true; + } + }); + return PsiUtilCore.toPsiElementArray(children); } PsiManager manager = psiDirectory.getManager(); @@ -198,11 +207,11 @@ public class ProjectViewDirectoryHelper { return PsiUtilCore.toPsiElementArray(directoriesOnTheWayToContentRoots); } - private boolean isInProject(VirtualFile dir) { + private boolean shouldBeShown(VirtualFile dir, ViewSettings settings) { DirectoryInfo directoryInfo = myIndex.getInfoForFile(dir); if (directoryInfo.isInProject()) return true; - if (!Registry.is("ide.hide.excluded.files")) { + if (!Registry.is("ide.hide.excluded.files") && settings instanceof ProjectViewSettings && ((ProjectViewSettings)settings).isShowExcludedFiles()) { return directoryInfo.isExcluded(); } return false; @@ -230,7 +239,7 @@ public class ProjectViewDirectoryHelper { vFile = dir.getVirtualFile(); if (!vFile.equals(projectFileIndex.getSourceRootForFile(vFile))) { // if is not a source root if (viewSettings.isHideEmptyMiddlePackages() && !skipDirectory(psiDir) && isEmptyMiddleDirectory(dir, true)) { - processPsiDirectoryChildren(dir, directoryChildrenInProject(projectFileIndex, dir), + processPsiDirectoryChildren(dir, directoryChildrenInProject(dir, viewSettings), container, projectFileIndex, moduleFileIndex, viewSettings, withSubDirectories); // expand it recursively continue; } diff --git a/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosPanel.java b/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosPanel.java index 97b3f8720f60..057082105eeb 100644 --- a/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosPanel.java @@ -22,6 +22,7 @@ package com.intellij.ide.todo; import com.intellij.ide.util.PropertiesComponent; import com.intellij.ide.util.scopeChooser.IgnoringComboBox; +import com.intellij.ide.util.scopeChooser.ScopeChooserCombo; import com.intellij.openapi.project.Project; import com.intellij.packageDependencies.DependencyValidationManager; import com.intellij.psi.search.scope.NonProjectFilesScope; @@ -44,47 +45,18 @@ import java.util.List; public class ScopeBasedTodosPanel extends TodoPanel { private static final String SELECTED_SCOPE = "TODO_SCOPE"; private final Alarm myAlarm; - private JComboBox myScopes; - private final NamedScopesHolder.ScopeListener myScopeListener; - private final NamedScopeManager myNamedScopeManager; - private final DependencyValidationManager myValidationManager; + private ScopeChooserCombo myScopes; public ScopeBasedTodosPanel(final Project project, TodoPanelSettings settings, Content content){ super(project,settings,false,content); myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, project); - final String scopeName = PropertiesComponent.getInstance(project).getValue(SELECTED_SCOPE); - rebuildModel(project, scopeName); - - myScopeListener = new NamedScopesHolder.ScopeListener() { - @Override - public void scopesChanged() { - final ScopeWrapper scope = (ScopeWrapper)myScopes.getSelectedItem(); - rebuildModel(project, scope != null ? scope.getName() : null); - } - }; - - myNamedScopeManager = NamedScopeManager.getInstance(project); - myNamedScopeManager.addScopeListener(myScopeListener); - - myValidationManager = DependencyValidationManager.getInstance(project); - myValidationManager.addScopeListener(myScopeListener); - - myScopes.setRenderer(new ListCellRendererWrapper<ScopeWrapper>(){ - @Override - public void customize(JList list, ScopeWrapper value, int index, boolean selected, boolean hasFocus) { - setText(value.getName()); - if (value.isSeparator()) { - setSeparator(); - } - } - }); - myScopes.addActionListener(new ActionListener() { + myScopes.getChildComponent().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { rebuildWithAlarm(ScopeBasedTodosPanel.this.myAlarm); - final ScopeWrapper selectedItem = (ScopeWrapper)myScopes.getSelectedItem(); - if (selectedItem != null) { - PropertiesComponent.getInstance(myProject).setValue(SELECTED_SCOPE, selectedItem.getName()); + final String selectedItemName = myScopes.getSelectedScopeName(); + if (selectedItemName != null) { + PropertiesComponent.getInstance(myProject).setValue(SELECTED_SCOPE, selectedItemName); } } }); @@ -92,67 +64,14 @@ public class ScopeBasedTodosPanel extends TodoPanel { } @Override - public void dispose() { - myNamedScopeManager.removeScopeListener(myScopeListener); - myValidationManager.removeScopeListener(myScopeListener); - super.dispose(); - } - - private void rebuildModel(Project project, String scopeName) { - final ArrayList<ScopeWrapper> scopes = new ArrayList<ScopeWrapper>(); - final DependencyValidationManager manager = DependencyValidationManager.getInstance(project); - - scopes.add(new ScopeWrapper("Predefined Scopes")); - List<NamedScope> predefinedScopesList = manager.getPredefinedScopes(); - NamedScope[] predefinedScopes = predefinedScopesList.toArray(new NamedScope[predefinedScopesList.size()]); - predefinedScopes = NonProjectFilesScope.removeFromList(predefinedScopes); - for (NamedScope predefinedScope : predefinedScopes) { - scopes.add(new ScopeWrapper(predefinedScope)); - } - - collectEditableScopes(scopes, manager, "Custom Project Scopes"); - collectEditableScopes(scopes, NamedScopeManager.getInstance(project), "Custom Local Scopes"); - - myScopes.setModel(new DefaultComboBoxModel(scopes.toArray(new ScopeWrapper[scopes.size()]))); - setSelection(scopeName, scopes); - } - - private void setSelection(@Nullable String scopeName, ArrayList<ScopeWrapper> scopes) { - boolean hasNonSeparators = false; - for (ScopeWrapper scope : scopes) { - if (!scope.isSeparator()) { - hasNonSeparators = true; - if (scopeName == null || scopeName.equals(scope.getName())) { - myScopes.setSelectedItem(scope); - return; - } - } - } - assert hasNonSeparators; - setSelection(null, scopes); - } - - private static void collectEditableScopes(ArrayList<ScopeWrapper> scopes, NamedScopesHolder manager, String separatorTitle) { - NamedScope[] editableScopes = manager.getEditableScopes(); - if (editableScopes.length > 0) { - scopes.add(new ScopeWrapper(separatorTitle)); - for (NamedScope scope : editableScopes) { - scopes.add(new ScopeWrapper(scope)); - } - } - } - - @Override protected JComponent createCenterComponent() { JPanel panel = new JPanel(new BorderLayout()); final JComponent component = super.createCenterComponent(); panel.add(component, BorderLayout.CENTER); - myScopes = new IgnoringComboBox() { - @Override - protected boolean isIgnored(Object item) { - return item instanceof ScopeWrapper && ((ScopeWrapper)item).isSeparator(); - } - }; + String preselect = PropertiesComponent.getInstance(myProject).getValue(SELECTED_SCOPE); + myScopes = new ScopeChooserCombo(myProject, false, true, preselect); + myScopes.setCurrentSelection(false); + myScopes.setUsageView(false); JPanel chooserPanel = new JPanel(new GridBagLayout()); final JLabel scopesLabel = new JLabel("Scope:"); @@ -177,32 +96,4 @@ public class ScopeBasedTodosPanel extends TodoPanel { builder.init(); return builder; } - - public static class ScopeWrapper { - private final String myName; - private final boolean mySeparator; - private NamedScope myNamedScope; - - private ScopeWrapper(NamedScope namedScope) { - mySeparator = false; - myNamedScope = namedScope; - myName = myNamedScope.getName(); - } - private ScopeWrapper(String name) { - mySeparator = true; - myName = name; - } - - public String getName() { - return myName; - } - - public NamedScope getNamedScope() { - return myNamedScope; - } - - public boolean isSeparator() { - return mySeparator; - } - } }
\ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosTreeBuilder.java index 2d7163a0d5b1..0dc79f911852 100644 --- a/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosTreeBuilder.java +++ b/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosTreeBuilder.java @@ -19,6 +19,7 @@ */ package com.intellij.ide.todo; +import com.intellij.ide.util.scopeChooser.ScopeChooserCombo; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; @@ -26,9 +27,9 @@ import javax.swing.*; import javax.swing.tree.DefaultTreeModel; public class ScopeBasedTodosTreeBuilder extends TodoTreeBuilder{ - private final JComboBox myScopes; + private final ScopeChooserCombo myScopes; - public ScopeBasedTodosTreeBuilder(JTree tree, DefaultTreeModel treeModel, Project project, JComboBox scopes){ + public ScopeBasedTodosTreeBuilder(JTree tree, DefaultTreeModel treeModel, Project project, ScopeChooserCombo scopes){ super(tree,treeModel,project); myScopes = scopes; } diff --git a/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosTreeStructure.java b/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosTreeStructure.java index 322cc44bc99c..500e17b56534 100644 --- a/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosTreeStructure.java +++ b/platform/lang-impl/src/com/intellij/ide/todo/ScopeBasedTodosTreeStructure.java @@ -24,22 +24,14 @@ import com.intellij.ide.todo.nodes.ToDoRootNode; import com.intellij.ide.util.scopeChooser.ScopeChooserCombo; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ChangeListManager; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.packageDependencies.DependencyValidationManager; import com.intellij.psi.PsiFile; -import com.intellij.psi.search.scope.packageSet.NamedScope; -import com.intellij.psi.search.scope.packageSet.NamedScopesHolder; -import com.intellij.psi.search.scope.packageSet.PackageSet; - -import javax.swing.*; -import java.util.Collection; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.SearchScope; public class ScopeBasedTodosTreeStructure extends TodoTreeStructure { - private final JComboBox myScopes; + private final ScopeChooserCombo myScopes; - public ScopeBasedTodosTreeStructure(Project project, JComboBox scopes) { + public ScopeBasedTodosTreeStructure(Project project, ScopeChooserCombo scopes) { super(project); myScopes = scopes; } @@ -48,12 +40,9 @@ public class ScopeBasedTodosTreeStructure extends TodoTreeStructure { public boolean accept(final PsiFile psiFile) { if (!psiFile.isValid()) return false; boolean isAffected = false; - final ScopeBasedTodosPanel.ScopeWrapper scope = (ScopeBasedTodosPanel.ScopeWrapper)myScopes.getSelectedItem(); - if (scope != null) { - final PackageSet value = scope.getNamedScope().getValue(); - if (value != null) { - isAffected = value.contains(psiFile, NamedScopesHolder.getHolder(myProject, scope.getName(), DependencyValidationManager.getInstance(myProject))); - } + SearchScope scope = myScopes.getSelectedScope(); + if (scope instanceof GlobalSearchScope) { + isAffected = ((GlobalSearchScope)scope).contains(psiFile.getVirtualFile()); } return isAffected && (myTodoFilter != null && myTodoFilter.accept(mySearchHelper, psiFile) || (myTodoFilter == null && mySearchHelper.getTodoItemsCount(psiFile) > 0)); diff --git a/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java b/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java index eb22b72eb810..37248fe8a909 100644 --- a/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java +++ b/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java @@ -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. @@ -26,7 +26,7 @@ import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ApplicationStarter; +import com.intellij.openapi.application.ApplicationStarterEx; import com.intellij.openapi.application.ex.ApplicationEx; import com.intellij.openapi.keymap.impl.ui.KeymapPanel; import com.intellij.openapi.options.SearchableConfigurable; @@ -50,8 +50,7 @@ import java.util.TreeSet; * Pass corresponding -Didea.platform.prefix=YOUR_IDE_PREFIX to vm options and choose main_YOUR_IDE module */ @SuppressWarnings({"CallToPrintStackTrace", "SynchronizeOnThis"}) -public class TraverseUIStarter implements ApplicationStarter { - private String OUTPUT_PATH; +public class TraverseUIStarter extends ApplicationStarterEx { @NonNls private static final String OPTIONS = "options"; @NonNls private static final String CONFIGURABLE = "configurable"; @NonNls private static final String ID = "id"; @@ -61,13 +60,19 @@ public class TraverseUIStarter implements ApplicationStarter { @NonNls private static final String PATH = "path"; @NonNls private static final String HIT = "hit"; + private String OUTPUT_PATH; + + @Override + public boolean isHeadless() { + return true; + } + @Override @NonNls public String getCommandName() { return "traverseUI"; } - @Override public void premain(String[] args) { OUTPUT_PATH = args[1]; diff --git a/platform/lang-impl/src/com/intellij/ide/util/PsiElementListCellRenderer.java b/platform/lang-impl/src/com/intellij/ide/util/PsiElementListCellRenderer.java index f51ec554485a..d0a0648285d6 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/PsiElementListCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/ide/util/PsiElementListCellRenderer.java @@ -102,7 +102,7 @@ public abstract class PsiElementListCellRenderer<T extends PsiElement> extends J setPaintFocusBorder(hasFocus && UIUtil.isToUseDottedCellBorder() && myFocusBorderEnabled); if (value instanceof PsiElement) { T element = (T)value; - String name = getElementText(element); + String name = element.isValid() ? getElementText(element) : "INVALID"; PsiFile psiFile = element.isValid() ? element.getContainingFile() : null; boolean isProblemFile = false; diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index 3e90f2310884..53d71d9794fa 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -54,6 +54,8 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.psi.PsiElement; @@ -518,23 +520,33 @@ public abstract class ChooseByNameBase { else { Component oppositeComponent = e.getOppositeComponent(); if (oppositeComponent == myCheckBox) { - myTextField.requestFocus(); + IdeFocusManager.getInstance(myProject).requestFocus(myTextField, true); return; } if (oppositeComponent != null && !(oppositeComponent instanceof JFrame) && myList.isShowing() && (oppositeComponent == myList || SwingUtilities.isDescendingFrom(myList, oppositeComponent))) { - myTextField.requestFocus();// Otherwise me may skip some KeyEvents + IdeFocusManager.getInstance(myProject).requestFocus(myTextField, true);// Otherwise me may skip some KeyEvents return; } + if (oppositeComponent != null) { + ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject); + ToolWindow toolWindow = toolWindowManager.getToolWindow(toolWindowManager.getActiveToolWindowId()); + if (toolWindow != null) { + JComponent toolWindowComponent = toolWindow.getComponent(); + if (SwingUtilities.isDescendingFrom(oppositeComponent, toolWindowComponent)) { + return; // Allow toolwindows to gain focus (used by QuickDoc shown in a toolwindow) + } + } + } + EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue(); if (queue instanceof IdeEventQueue) { if (!((IdeEventQueue)queue).wasRootRecentlyClicked(oppositeComponent)) { Component root = SwingUtilities.getRoot(myTextField); if (root != null && root.isShowing()) { - root.requestFocus(); - myTextField.requestFocus(); + IdeFocusManager.getInstance(myProject).requestFocus(myTextField, true); return; } } @@ -641,7 +653,7 @@ public abstract class ChooseByNameBase { @Override public boolean onClick(@NotNull MouseEvent e, int clickCount) { if (!myTextField.hasFocus()) { - myTextField.requestFocus(); + IdeFocusManager.getInstance(myProject).requestFocus(myTextField, true); } if (clickCount == 2) { diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java index c40831d276de..c26bd353de50 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java @@ -62,6 +62,7 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModelE protected ContributorsBasedGotoByModel(@NotNull Project project, @NotNull ChooseByNameContributor[] contributors) { myProject = project; myContributors = contributors; + assert !Arrays.asList(contributors).contains(null); } @Override @@ -95,7 +96,7 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModelE ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); Processor<ChooseByNameContributor> processor = new ReadActionProcessor<ChooseByNameContributor>() { @Override - public boolean processInReadAction(ChooseByNameContributor contributor) { + public boolean processInReadAction(@NotNull ChooseByNameContributor contributor) { try { if (!myProject.isDisposed()) { long contributorStarted = System.currentTimeMillis(); @@ -185,13 +186,15 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModelE } @NotNull - public Object[] getElementsByName(final String name, final FindSymbolParameters parameters, @NotNull final ProgressIndicator canceled) { + public Object[] getElementsByName(@NotNull final String name, + @NotNull final FindSymbolParameters parameters, + @NotNull final ProgressIndicator canceled) { long elementByNameStarted = System.currentTimeMillis(); final List<NavigationItem> items = Collections.synchronizedList(new ArrayList<NavigationItem>()); Processor<ChooseByNameContributor> processor = new Processor<ChooseByNameContributor>() { @Override - public boolean process(ChooseByNameContributor contributor) { + public boolean process(@NotNull ChooseByNameContributor contributor) { if (myProject.isDisposed()) { return true; } diff --git a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java index aef7c9a17e74..8297a3db8e1f 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java +++ b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java @@ -71,6 +71,8 @@ public class ScopeChooserCombo extends ComboboxWithBrowseButton implements Dispo private NamedScopesHolder.ScopeListener myScopeListener; private NamedScopeManager myNamedScopeManager; private DependencyValidationManager myValidationManager; + private boolean myCurrentSelection = true; + private boolean myUsageView = true; public ScopeChooserCombo() { super(new IgnoringComboBox(){ @@ -118,6 +120,14 @@ public class ScopeChooserCombo extends ComboboxWithBrowseButton implements Dispo selectScope(preselect); } + public void setCurrentSelection(boolean currentSelection) { + myCurrentSelection = currentSelection; + } + + public void setUsageView(boolean usageView) { + myUsageView = usageView; + } + @Override public void dispose() { super.dispose(); @@ -220,7 +230,7 @@ public class ScopeChooserCombo extends ComboboxWithBrowseButton implements Dispo private void createPredefinedScopeDescriptors(DefaultComboBoxModel model) { @SuppressWarnings("deprecation") final DataContext context = DataManager.getInstance().getDataContext(); - for (SearchScope scope : getPredefinedScopes(myProject, context, mySuggestSearchInLibs, myPrevSearchFiles, true, true)) { + for (SearchScope scope : getPredefinedScopes(myProject, context, mySuggestSearchInLibs, myPrevSearchFiles, myCurrentSelection, myUsageView)) { model.addElement(new ScopeDescriptor(scope)); } for (ScopeDescriptorProvider provider : Extensions.getExtensions(ScopeDescriptorProvider.EP_NAME)) { diff --git a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeDescriptorProvider.java b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeDescriptorProvider.java index fb879abd2595..44baafa0b86e 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeDescriptorProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeDescriptorProvider.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; public interface ScopeDescriptorProvider { + ScopeDescriptor[] EMPTY = new ScopeDescriptor[0]; ExtensionPointName<ScopeDescriptorProvider> EP_NAME = ExtensionPointName.create("com.intellij.scopeDescriptorProvider"); @NotNull diff --git a/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java index d0288d71a9a2..da44ae6c123c 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java @@ -212,13 +212,24 @@ public class CaretModelWindow implements CaretModel { @Override public void setCaretsAndSelections(@NotNull List<CaretState> caretStates) { + List<CaretState> convertedStates = convertCaretStates(caretStates); + myDelegate.setCaretsAndSelections(convertedStates); + } + + @Override + public void setCaretsAndSelections(@NotNull List<CaretState> caretStates, boolean updateSystemSelection) { + List<CaretState> convertedStates = convertCaretStates(caretStates); + myDelegate.setCaretsAndSelections(convertedStates, updateSystemSelection); + } + + private List<CaretState> convertCaretStates(List<CaretState> caretStates) { List<CaretState> convertedStates = new ArrayList<CaretState>(caretStates.size()); for (CaretState state : caretStates) { convertedStates.add(new CaretState(injectedToHost(state.getCaretPosition()), injectedToHost(state.getSelectionStart()), injectedToHost(state.getSelectionEnd()))); } - myDelegate.setCaretsAndSelections(convertedStates); + return convertedStates; } private LogicalPosition injectedToHost(@Nullable LogicalPosition position) { diff --git a/platform/lang-impl/src/com/intellij/injected/editor/InjectedCaret.java b/platform/lang-impl/src/com/intellij/injected/editor/InjectedCaret.java index e52fa66ccefc..ec958fdc557a 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/InjectedCaret.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/InjectedCaret.java @@ -165,6 +165,12 @@ public class InjectedCaret implements Caret { } @Override + public void setSelection(int startOffset, int endOffset, boolean updateSystemSelection) { + TextRange hostRange = myEditorWindow.getDocument().injectedToHost(new ProperTextRange(startOffset, endOffset)); + myDelegate.setSelection(hostRange.getStartOffset(), hostRange.getEndOffset(), updateSystemSelection); + } + + @Override public void setSelection(int startOffset, @Nullable VisualPosition endPosition, int endOffset) { TextRange hostRange = myEditorWindow.getDocument().injectedToHost(new ProperTextRange(startOffset, endOffset)); myDelegate.setSelection(hostRange.getStartOffset(), endPosition, hostRange.getEndOffset()); @@ -177,6 +183,12 @@ public class InjectedCaret implements Caret { } @Override + public void setSelection(@Nullable VisualPosition startPosition, int startOffset, @Nullable VisualPosition endPosition, int endOffset, boolean updateSystemSelection) { + TextRange hostRange = myEditorWindow.getDocument().injectedToHost(new ProperTextRange(startOffset, endOffset)); + myDelegate.setSelection(startPosition, hostRange.getStartOffset(), endPosition, hostRange.getEndOffset(), updateSystemSelection); + } + + @Override public void removeSelection() { myDelegate.removeSelection(); } diff --git a/platform/lang-impl/src/com/intellij/internal/ImageDuplicateResultsDialog.java b/platform/lang-impl/src/com/intellij/internal/ImageDuplicateResultsDialog.java index c7c62288c158..53d4a3edd7ef 100644 --- a/platform/lang-impl/src/com/intellij/internal/ImageDuplicateResultsDialog.java +++ b/platform/lang-impl/src/com/intellij/internal/ImageDuplicateResultsDialog.java @@ -39,7 +39,6 @@ import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBList; import com.intellij.ui.components.JBScrollPane; -import com.intellij.ui.popup.NotLookupOrSearchCondition; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.Function; import com.intellij.util.NotNullFunction; @@ -232,7 +231,6 @@ public class ImageDuplicateResultsDialog extends DialogWrapper { final JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(viewComponent, viewComponent.getPreferredFocusableComponent()) - .setRequestFocusCondition(myProject, NotLookupOrSearchCondition.INSTANCE) .setProject(myProject) .setDimensionServiceKey(myProject, DocumentationManager.JAVADOC_LOCATION_AND_SIZE, false) .setResizable(true) diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java index dfaa6501831b..cd1ec63d1879 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java @@ -101,7 +101,7 @@ import java.util.regex.Pattern; */ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disposable { private static final String REFS_CACHE = "References Resolve Cache"; - private static final Color SELECTION_BG_COLOR = new JBColor(new Color(0x009999), new Color(0, 80, 80)); + private static final Color BOX_COLOR = new JBColor(new Color(0xFC6C00), new Color(0xDE6C01)); private static final Logger LOG = Logger.getInstance("#com.intellij.internal.psiView.PsiViewerDialog"); private final Project myProject; @@ -133,7 +133,6 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp @Nullable private BlockTreeBuilder myBlockTreeBuilder; private RangeHighlighter myHighlighter; - private RangeHighlighter myIntersectHighlighter; private HashMap<PsiElement, BlockTreeNode> myPsiToBlockMap; private final Set<SourceWrapper> mySourceWrappers = ContainerUtil.newTreeSet(); @@ -163,7 +162,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp } @Override - public int compare(String o1, String o2) { + public int compare(@NotNull String o1, @NotNull String o2) { if (o1.equals(myOnTop)) return -1; if (o2.equals(myOnTop)) return 1; return o1.compareToIgnoreCase(o2); @@ -194,8 +193,8 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp } @Override - public int compareTo(final SourceWrapper o) { - return o == null ? -1 : getText().compareToIgnoreCase(o.getText()); + public int compareTo(@NotNull final SourceWrapper o) { + return getText().compareToIgnoreCase(o.getText()); } } @@ -242,7 +241,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp final TreeCellRenderer renderer = myPsiTree.getCellRenderer(); myPsiTree.setCellRenderer(new TreeCellRenderer() { @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + public Component getTreeCellRendererComponent(@NotNull JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { final Component c = renderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); if (value instanceof DefaultMutableTreeNode) { final Object userObject = ((DefaultMutableTreeNode)value).getUserObject(); @@ -251,7 +250,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp if (c instanceof NodeRenderer) { ((NodeRenderer)c).setToolTipText(element == null ? null : element.getClass().getName()); } - if ((element instanceof PsiElement && FileContextUtil.getFileContext(((PsiElement)element).getContainingFile()) != null) || + if (element instanceof PsiElement && FileContextUtil.getFileContext(((PsiElement)element).getContainingFile()) != null || element instanceof ViewerTreeStructure.Inject) { final TextAttributes attr = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.INJECTED_LANGUAGE_FRAGMENT); c.setBackground(attr.getBackgroundColor()); @@ -271,7 +270,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp myRefs.getSelectionModel().addListSelectionListener(listener); myRefs.setCellRenderer(new DefaultListCellRenderer() { @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + public Component getListCellRendererComponent(@NotNull JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { final Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (resolve(index) == null) { comp.setForeground(JBColor.RED); @@ -289,7 +288,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp getPeer().getWindow().setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() { @Override - public Component getInitialComponent(Window window) { + public Component getInitialComponent(@NotNull Window window) { return myEditor.getComponent(); } }); @@ -324,7 +323,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp mySourceWrappers.add(wrapper); if (lastUsed == null && wrapper.getText().equals(type)) lastUsed = wrapper; if (myCurrentFile != null && wrapper.myFileType instanceof LanguageFileType && - ((LanguageFileType)wrapper.myFileType).equals(curLanguage.getAssociatedFileType())) { + wrapper.myFileType.equals(curLanguage.getAssociatedFileType())) { lastUsed = wrapper; } } @@ -347,7 +346,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp }; myFileTypeComboBox.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { updateDialectsCombo(null); updateExtensionsCombo(); updateEditor(); @@ -355,7 +354,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp }); myDialectComboBox.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { updateEditor(); } }); @@ -382,14 +381,14 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp final ViewerTreeStructure psiTreeStructure = (ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure(); myShowWhiteSpacesBox.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { psiTreeStructure.setShowWhiteSpaces(myShowWhiteSpacesBox.isSelected()); myPsiTreeBuilder.queueUpdate(); } }); myShowTreeNodesCheckBox.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { psiTreeStructure.setShowTreeNodes(myShowTreeNodesCheckBox.isSelected()); myPsiTreeBuilder.queueUpdate(); } @@ -402,7 +401,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp myBlockStructurePanel.setVisible(settings.showBlocks); myShowBlocksCheckBox.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { if (!myShowBlocksCheckBox.isSelected()) { settings.blockRefDividerLocation = myBlockRefSplitPane.getDividerLocation(); } @@ -473,14 +472,14 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp registerKeyboardAction(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { focusEditor(); } }, KeyStroke.getKeyStroke(KeyEvent.VK_T, mask)); registerKeyboardAction(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { focusTree(); } }, KeyStroke.getKeyStroke(KeyEvent.VK_S, mask)); @@ -488,21 +487,21 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp registerKeyboardAction(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { focusBlockTree(); } }, KeyStroke.getKeyStroke(KeyEvent.VK_K, mask)); registerKeyboardAction(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { focusRefs(); } }, KeyStroke.getKeyStroke(KeyEvent.VK_R, mask)); registerKeyboardAction(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { if (myRefs.isFocusOwner()) { focusBlockTree(); } @@ -548,26 +547,6 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp myBlockTreeSeparator.setLabelFor(myBlockTree); } - private void updateIntersectHighlighter(int highlightStart, int highlightEnd) { - if (myIntersectHighlighter != null) { - myEditor.getMarkupModel().removeHighlighter(myIntersectHighlighter); - myIntersectHighlighter.dispose(); - } - if (myEditor.getSelectionModel().hasSelection()) { - int selectionStart = myEditor.getSelectionModel().getSelectionStart(); - int selectionEnd = myEditor.getSelectionModel().getSelectionEnd(); - TextRange resRange = new TextRange(highlightStart, highlightEnd).intersection(new TextRange(selectionStart, selectionEnd)); - if (resRange != null) { - TextAttributes attributes = new TextAttributes(); - attributes.setBackgroundColor(Color.LIGHT_GRAY); - attributes.setForegroundColor(Color.white); - myIntersectHighlighter = myEditor.getMarkupModel() - .addRangeHighlighter(resRange.getStartOffset(), resRange.getEndOffset(), HighlighterLayer.LAST + 1, attributes, - HighlighterTargetArea.EXACT_RANGE); - } - } - } - @Nullable private PsiElement getPsiElement() { final TreePath path = myPsiTree.getSelectionPath(); @@ -676,7 +655,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp protected Action[] createActions() { AbstractAction copyPsi = new AbstractAction("Cop&y PSI") { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { PsiElement element = parseText(myEditor.getDocument().getText()); List<PsiElement> allToParse = new ArrayList<PsiElement>(); if (element instanceof PsiFile) { @@ -735,7 +714,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp myPsiToBlockMap = new HashMap<PsiElement, BlockTreeNode>(); final PsiElement psiFile = ((ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure()).getRootPsiElement(); initMap(rootNode, psiFile); - PsiElement rootPsi = (rootNode.getBlock() instanceof ASTBlock) ? + PsiElement rootPsi = rootNode.getBlock() instanceof ASTBlock ? ((ASTBlock)rootNode.getBlock()).getNode().getPsi() : rootElement; BlockTreeNode blockNode = myPsiToBlockMap.get(rootPsi); @@ -856,12 +835,12 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp public MyPsiTreeSelectionListener() { myAttributes = new TextAttributes(); - myAttributes.setBackgroundColor(SELECTION_BG_COLOR); - myAttributes.setForegroundColor(Color.white); + myAttributes.setEffectColor(BOX_COLOR); + myAttributes.setEffectType(EffectType.ROUNDED_BOX); } @Override - public void valueChanged(TreeSelectionEvent e) { + public void valueChanged(@NotNull TreeSelectionEvent e) { if (!myEditor.getDocument().getText().equals(myLastParsedText) || myBlockTree.hasFocus()) return; TreePath path = myPsiTree.getSelectionPath(); clearSelection(); @@ -887,8 +866,6 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp final int textLength = myEditor.getDocument().getTextLength(); if (end <= textLength) { myHighlighter = myEditor.getMarkupModel().addRangeHighlighter(start, end, HighlighterLayer.LAST, myAttributes, HighlighterTargetArea.EXACT_RANGE); - updateIntersectHighlighter(start, end); - if (myPsiTree.hasFocus()) { myEditor.getCaretModel().moveToOffset(start); myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); @@ -946,12 +923,12 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp public MyBlockTreeSelectionListener() { myAttributes = new TextAttributes(); - myAttributes.setBackgroundColor(SELECTION_BG_COLOR); - myAttributes.setForegroundColor(Color.white); + myAttributes.setEffectColor(BOX_COLOR); + myAttributes.setEffectType(EffectType.ROUNDED_BOX); } @Override - public void valueChanged(TreeSelectionEvent e) { + public void valueChanged(@NotNull TreeSelectionEvent e) { if (myIgnoreBlockTreeSelectionMarker > 0 || myBlockTreeBuilder == null) { return; } @@ -988,7 +965,6 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp if (end <= textLength) { myHighlighter = myEditor.getMarkupModel() .addRangeHighlighter(start, end, HighlighterLayer.LAST, myAttributes, HighlighterTargetArea.EXACT_RANGE); - updateIntersectHighlighter(start, end); myEditor.getCaretModel().moveToOffset(start); myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); @@ -1112,7 +1088,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp private class GoToListener implements KeyListener, MouseListener, ListSelectionListener { private RangeHighlighter myListenerHighlighter; private final TextAttributes myAttributes = - new TextAttributes(Color.white, SELECTION_BG_COLOR, JBColor.RED, EffectType.BOXED, Font.PLAIN); + new TextAttributes(JBColor.RED, null, null, null, Font.PLAIN); private void navigate() { final Object value = myRefs.getSelectedValue(); @@ -1124,21 +1100,21 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp } @Override - public void keyPressed(KeyEvent e) { + public void keyPressed(@NotNull KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { navigate(); } } @Override - public void mouseClicked(MouseEvent e) { + public void mouseClicked(@NotNull MouseEvent e) { if (e.getClickCount() > 1) { navigate(); } } @Override - public void valueChanged(ListSelectionEvent e) { + public void valueChanged(@NotNull ListSelectionEvent e) { clearSelection(); updateDialectsCombo(null); updateExtensionsCombo(); @@ -1176,17 +1152,17 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp } @Override - public void keyTyped(KeyEvent e) {} + public void keyTyped(@NotNull KeyEvent e) {} @Override public void keyReleased(KeyEvent e) {} @Override - public void mousePressed(MouseEvent e) {} + public void mousePressed(@NotNull MouseEvent e) {} @Override - public void mouseReleased(MouseEvent e) {} + public void mouseReleased(@NotNull MouseEvent e) {} @Override - public void mouseEntered(MouseEvent e) {} + public void mouseEntered(@NotNull MouseEvent e) {} @Override - public void mouseExited(MouseEvent e) {} + public void mouseExited(@NotNull MouseEvent e) {} } private void updateEditor() { @@ -1247,7 +1223,6 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp if (myEditor.getContentComponent().hasFocus()) { TextRange rangeInHostFile = InjectedLanguageManager.getInstance(myProject).injectedToHost(element, element.getTextRange()); selectBlockNode(findBlockNode(rangeInHostFile, true)); - updateIntersectHighlighter(myHighlighter.getStartOffset(), myHighlighter.getEndOffset()); } } myPsiTreeBuilder.select(element); @@ -1270,13 +1245,6 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp return myLastParsedTextHashCode == myNewDocumentHashCode && myEditor.getContentComponent().hasFocus(); } - @Nullable - private PsiFile getPsiFile() { - ViewerTreeStructure treeStructure = (ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure(); - final PsiElement root = treeStructure != null ? treeStructure.getRootPsiElement() : null; - return root instanceof PsiFile ? (PsiFile)root : null; - } - @Override public void beforeDocumentChange(DocumentEvent event) { @@ -1297,7 +1265,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp } @Override - public void focusGained(final FocusEvent e) { + public void focusGained(@NotNull final FocusEvent e) { final Component from = e.getOppositeComponent(); if (!e.isTemporary() && from != null && !myComboBox.isPopupVisible() && isUnder(from, myParent)) { myComboBox.setPopupVisible(true); diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java index c62954177884..ea6d2fcc59fc 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java @@ -37,6 +37,7 @@ class ModuleStateStorageManager extends StateStorageManagerImpl { return new ModuleStoreImpl.ModuleFileData(ROOT_TAG_NAME, myModule); } + @Nullable @Override protected String getOldStorageSpec(Object component, final String componentName, final StateStorageOperation operation) { return ModuleStoreImpl.DEFAULT_STATE_STORAGE; diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java index a96432e2b64c..962aa81c3e59 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java @@ -37,8 +37,12 @@ import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.EmptyRunnable; -import com.intellij.openapi.vfs.*; -import com.intellij.openapi.vfs.impl.BulkVirtualFileListenerAdapter; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.openapi.vfs.newvfs.events.VFileMoveEvent; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.file.impl.FileManagerImpl; @@ -48,8 +52,11 @@ import com.intellij.util.indexing.FileBasedIndexProjectHandler; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.IOException; +import java.util.Arrays; +import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -86,33 +93,39 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater } }); - myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkVirtualFileListenerAdapter(new VirtualFileAdapter() { + myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() { @Override - public void fileCreated(@NotNull final VirtualFileEvent event) { - final VirtualFile file = event.getFile(); - final FilePropertyPusher[] pushers = file.isDirectory() ? myPushers : myFilePushers; - if (!event.isFromRefresh() || !file.isDirectory()) { - // push synchronously to avoid entering dumb mode in the middle of a meaningful write action - // avoid dumb mode for just one file - doPushRecursively(file, pushers, ProjectRootManager.getInstance(myProject).getFileIndex()); - } - else { - schedulePushRecursively(file, pushers); - } - } + public void after(@NotNull List<? extends VFileEvent> events) { + List<Runnable> delayedTasks = ContainerUtil.newArrayList(); + for (VFileEvent event : events) { + final VirtualFile file = event.getFile(); + if (file == null) continue; - @Override - public void fileMoved(@NotNull final VirtualFileMoveEvent event) { - final VirtualFile file = event.getFile(); - final FilePropertyPusher[] pushers = file.isDirectory() ? myPushers : myFilePushers; - if (pushers.length == 0) return; - for (FilePropertyPusher pusher : pushers) { - file.putUserData(pusher.getFileDataKey(), null); + final FilePropertyPusher[] pushers = file.isDirectory() ? myPushers : myFilePushers; + if (pushers.length == 0) continue; + + if (event instanceof VFileCreateEvent) { + if (!event.isFromRefresh() || !file.isDirectory()) { + // push synchronously to avoid entering dumb mode in the middle of a meaningful write action + // avoid dumb mode for just one file + doPushRecursively(file, pushers, ProjectRootManager.getInstance(myProject).getFileIndex()); + } + else { + ContainerUtil.addIfNotNull(delayedTasks, createRecursivePushTask(file, pushers)); + } + } else if (event instanceof VFileMoveEvent) { + for (FilePropertyPusher pusher : pushers) { + file.putUserData(pusher.getFileDataKey(), null); + } + // push synchronously to avoid entering dumb mode in the middle of a meaningful write action + doPushRecursively(file, pushers, ProjectRootManager.getInstance(myProject).getFileIndex()); + } + } + if (!delayedTasks.isEmpty()) { + queueTasks(delayedTasks); } - // push synchronously to avoid entering dumb mode in the middle of a meaningful write action - doPushRecursively(file, pushers, ProjectRootManager.getInstance(myProject).getFileIndex()); } - })); + }); } }); } @@ -128,7 +141,7 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater @Override public void pushRecursively(VirtualFile file, Project project) { - PushedFilePropertiesUpdaterImpl.this.schedulePushRecursively(file, pusher); + queueTasks(ContainerUtil.createMaybeSingletonList(createRecursivePushTask(file, new FilePropertyPusher[]{pusher}))); } }); } @@ -140,16 +153,17 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater doPushAll(myPushers); } - private void schedulePushRecursively(final VirtualFile dir, final FilePropertyPusher... pushers) { - if (pushers.length == 0) return; + @Nullable + private Runnable createRecursivePushTask(final VirtualFile dir, final FilePropertyPusher[] pushers) { + if (pushers.length == 0) return null; final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); - if (!fileIndex.isInContent(dir)) return; - queueTask(new Runnable() { + if (!fileIndex.isInContent(dir)) return null; + return new Runnable() { @Override public void run() { doPushRecursively(dir, pushers, fileIndex); } - }); + }; } private void doPushRecursively(VirtualFile dir, final FilePropertyPusher[] pushers, ProjectFileIndex fileIndex) { @@ -162,8 +176,10 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater }); } - private void queueTask(Runnable action) { - myTasks.offer(action); + private void queueTasks(List<? extends Runnable> actions) { + for (Runnable action : actions) { + myTasks.offer(action); + } final DumbModeTask task = new DumbModeTask() { @Override public void performInDumbMode(@NotNull ProgressIndicator indicator) { @@ -221,12 +237,12 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater @Override public void pushAll(final FilePropertyPusher... pushers) { - queueTask(new Runnable() { + queueTasks(Arrays.asList(new Runnable() { @Override public void run() { doPushAll(pushers); } - }); + })); } private void doPushAll(final FilePropertyPusher[] pushers) { diff --git a/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java b/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java index 0978f8f09ec7..65f2d758fcfd 100644 --- a/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java +++ b/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java @@ -17,6 +17,7 @@ package com.intellij.openapi.util.registry; import com.intellij.icons.AllIcons; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationInfo; @@ -27,6 +28,7 @@ import com.intellij.openapi.application.impl.LaterInvocator; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ShadowAction; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; import com.intellij.ui.table.JBTable; import com.intellij.util.PlatformIcons; @@ -54,6 +56,7 @@ import java.util.List; * @author Konstantin Bulenkov */ public class RegistryUi implements Disposable { + private static final String RECENT_PROPERTIES_KEY = "RegistryRecentKeys"; private final JBTable myTable; private final JTextArea myDescriptionLabel; @@ -143,6 +146,7 @@ public class RegistryUi implements Disposable { RegistryValue rv = myModel.getRegistryValue(row); if (rv.isBoolean()) { rv.setValue(!rv.asBoolean()); + keyChanged(rv.getKey()); for (int i : new int[]{0, 1, 2}) myModel.fireTableCellUpdated(row, i); revaliateActions(); if (search.isPopupActive()) search.hidePopup(); @@ -217,10 +221,21 @@ public class RegistryUi implements Disposable { private MyTableModel() { myAll = Registry.getAll(); + final List<String> recent = getRecent(); + Collections.sort(myAll, new Comparator<RegistryValue>() { @Override public int compare(@NotNull RegistryValue o1, @NotNull RegistryValue o2) { - return o1.getKey().compareTo(o2.getKey()); + final String key1 = o1.getKey(); + final String key2 = o2.getKey(); + final int i1 = recent.indexOf(key1); + final int i2 = recent.indexOf(key2); + final boolean c1 = i1 != -1; + final boolean c2 = i2 != -1; + if (c1 && !c2) return -1; + if (!c1 && c2) return 1; + if (c1 && c2) return i1 - i2; + return key1.compareToIgnoreCase(key2); } }); } @@ -264,6 +279,19 @@ public class RegistryUi implements Disposable { } } + private static List<String> getRecent() { + String value = PropertiesComponent.getInstance().getValue(RECENT_PROPERTIES_KEY); + return StringUtil.isEmpty(value) ? new ArrayList<String>(0) : StringUtil.split(value, "="); + } + + private static void keyChanged(String key) { + final List<String> recent = getRecent(); + recent.remove(key); + recent.add(0, key); + final String newValue = StringUtil.join(recent, "="); + PropertiesComponent.getInstance().setValue(RECENT_PROPERTIES_KEY, newValue); + } + public boolean show() { DialogWrapper dialog = new DialogWrapper(true) { { @@ -468,6 +496,7 @@ public class RegistryUi implements Disposable { } else { myValue.setValue(myField.getText().trim()); } + keyChanged(myValue.getKey()); } revaliateActions(); return super.stopCellEditing(); diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/CheckinHandlerUtil.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/CheckinHandlerUtil.java index 7a6b61f4722b..4a5a644d4fbe 100644 --- a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/CheckinHandlerUtil.java +++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/CheckinHandlerUtil.java @@ -20,6 +20,7 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; +import com.intellij.openapi.roots.GeneratedSourcesFilter; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.vfs.VfsUtilCore; @@ -34,11 +35,22 @@ import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; import javax.swing.*; import java.util.ArrayList; import java.util.Collection; +import java.util.List; /** * @author oleg */ public class CheckinHandlerUtil { + public static List<VirtualFile> filterOutGeneratedAndExcludedFiles(@NotNull Collection<VirtualFile> files, @NotNull Project project) { + ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(project); + List<VirtualFile> result = new ArrayList<VirtualFile>(files.size()); + for (VirtualFile file : files) { + if (!fileIndex.isExcluded(file) && !GeneratedSourcesFilter.isGeneratedSourceByAnyFilter(file, project)) { + result.add(file); + } + } + return result; + } public static PsiFile[] getPsiFiles(final Project project, final Collection<VirtualFile> selectedFiles) { ArrayList<PsiFile> result = new ArrayList<PsiFile>(); diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/actions/AnalyzeDependenciesOnSpecifiedTargetHandler.java b/platform/lang-impl/src/com/intellij/packageDependencies/actions/AnalyzeDependenciesOnSpecifiedTargetHandler.java index ffc682269563..7aebba7dfe41 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/actions/AnalyzeDependenciesOnSpecifiedTargetHandler.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/actions/AnalyzeDependenciesOnSpecifiedTargetHandler.java @@ -36,7 +36,7 @@ import java.util.*; */ public class AnalyzeDependenciesOnSpecifiedTargetHandler extends DependenciesHandlerBase { private static final NotificationGroup NOTIFICATION_GROUP = - NotificationGroup.toolWindowGroup("Dependencies", ToolWindowId.DEPENDENCIES, true); + NotificationGroup.toolWindowGroup("Dependencies", ToolWindowId.DEPENDENCIES); private final GlobalSearchScope myTargetScope; public AnalyzeDependenciesOnSpecifiedTargetHandler(@NotNull Project project, @NotNull AnalysisScope scope, @NotNull GlobalSearchScope targetScope) { diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeRenderer.java index 43b791cbe6a2..280f436b7bc5 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeRenderer.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeRenderer.java @@ -27,35 +27,36 @@ import com.intellij.codeInspection.ex.InspectionToolWrapper; import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; import com.intellij.ide.ui.search.SearchUtil; import com.intellij.profile.codeInspection.ui.ToolDescriptors; -import com.intellij.ui.ColoredTreeCellRenderer; +import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.ui.PlatformColors; import com.intellij.util.ui.UIUtil; +import org.jdesktop.swingx.renderer.DefaultTreeRenderer; import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -public abstract class InspectionsConfigTreeRenderer extends ColoredTreeCellRenderer { +public abstract class InspectionsConfigTreeRenderer extends DefaultTreeRenderer { protected abstract String getFilter(); @Override - public void customizeCellRenderer(@NotNull final JTree tree, - final Object value, - final boolean selected, - final boolean expanded, - final boolean leaf, - final int row, - final boolean hasFocus) { - if (!(value instanceof InspectionConfigTreeNode)) return; + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean selected, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) { + final SimpleColoredComponent component = new SimpleColoredComponent(); + if (!(value instanceof InspectionConfigTreeNode)) return component; InspectionConfigTreeNode node = (InspectionConfigTreeNode)value; Object object = node.getUserObject(); final Color background = selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeTextBackground(); - UIUtil.changeBackGround(this, background); + UIUtil.changeBackGround(component, background); Color foreground = selected ? UIUtil.getTreeSelectionForeground() : node.isProperSetting() ? PlatformColors.BLUE : UIUtil.getTreeTextForeground(); @@ -75,12 +76,13 @@ public abstract class InspectionsConfigTreeRenderer extends ColoredTreeCellRende } if (text != null) { - SearchUtil.appendFragments(getFilter(), text, style, foreground, background, this); + SearchUtil.appendFragments(getFilter(), text, style, foreground, background, component); } if (hint != null) { - append(" " + hint, selected ? new SimpleTextAttributes(Font.PLAIN, foreground) : SimpleTextAttributes.GRAYED_ATTRIBUTES); + component.append(" " + hint, selected ? new SimpleTextAttributes(Font.PLAIN, foreground) : SimpleTextAttributes.GRAYED_ATTRIBUTES); } - setForeground(foreground); + component.setForeground(foreground); + return component; } @Nullable diff --git a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java index 32a2e38384d9..76377ef6b98e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java @@ -554,22 +554,4 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run boolean isEnabled() { return myEnabled; } - - @TestOnly - public void waitUntilAllCommitted(long timeout) throws InterruptedException { - if (!myEnabled) { - throw new IllegalStateException("DocumentCommitThread is disabled"); - } - int attempts = 0; - int delay = 100; - synchronized (documentsToCommit) { - while(!documentsToCommit.isEmpty() || currentTask != null) { - documentsToCommit.wait(delay); - if (delay * attempts > timeout) { - throw new RuntimeException("timeout"); - } - attempts++; - } - } - } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java index 17dd2bca1f17..8b629875209b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java @@ -33,6 +33,7 @@ import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.PushedFilePropertiesUpdater; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.io.FileUtilRt; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.impl.BulkVirtualFileListenerAdapter; import com.intellij.psi.*; @@ -237,7 +238,7 @@ public class PsiVFSListener extends VirtualFileAdapter { } } else { - if (!isExcludeRoot(vFile) && !myFileTypeManager.isFileIgnored(newName)) { + if ((!Registry.is("ide.hide.excluded.files") || !isExcludeRoot(vFile)) && !myFileTypeManager.isFileIgnored(newName)) { myManager.beforeChildAddition(treeEvent); } } @@ -443,7 +444,8 @@ public class PsiVFSListener extends VirtualFileAdapter { public void run() { PsiTreeChangeEventImpl treeEvent = new PsiTreeChangeEventImpl(myManager); - boolean isExcluded = vFile.isDirectory() && myProjectRootManager.getFileIndex().isExcluded(vFile); + boolean isExcluded = vFile.isDirectory() && + Registry.is("ide.hide.excluded.files") && myProjectRootManager.getFileIndex().isExcluded(vFile); if (oldParentDir != null && !isExcluded) { if (newParentDir != null) { treeEvent.setOldParent(oldParentDir); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java index c5b183c3594b..f99d47201a20 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java @@ -56,20 +56,22 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; public class PostprocessReformattingAspect implements PomModelAspect { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PostprocessReformattingAspect"); private final Project myProject; private final PsiManager myPsiManager; private final TreeAspect myTreeAspect; - private final Map<FileViewProvider, List<ASTNode>> myReformatElements = new HashMap<FileViewProvider, List<ASTNode>>(); - private volatile int myDisabledCounter = 0; - private final Set<FileViewProvider> myUpdatedProviders = new HashSet<FileViewProvider>(); - private final AtomicInteger myPostponedCounter = new AtomicInteger(); private static final Key<Throwable> REFORMAT_ORIGINATOR = Key.create("REFORMAT_ORIGINATOR"); private static final boolean STORE_REFORMAT_ORIGINATOR_STACKTRACE = ApplicationManager.getApplication().isInternal(); + private final ThreadLocal<Context> myContext = new ThreadLocal<Context>() { + @Override + protected Context initialValue() { + return new Context(); + } + }; + public PostprocessReformattingAspect(Project project, PsiManager psiManager, TreeAspect treeAspect,final CommandProcessor processor) { myProject = project; myPsiManager = psiManager; @@ -113,12 +115,12 @@ public class PostprocessReformattingAspect implements PomModelAspect { public <T> T disablePostprocessFormattingInside(@NotNull Computable<T> computable) { try { - myDisabledCounter++; + getContext().myDisabledCounter++; return computable.compute(); } finally { - myDisabledCounter--; - LOG.assertTrue(myDisabledCounter > 0 || !isDisabled()); + getContext().myDisabledCounter--; + LOG.assertTrue(getContext().myDisabledCounter > 0 || !isDisabled()); } } @@ -145,13 +147,13 @@ public class PostprocessReformattingAspect implements PomModelAspect { } private void incrementPostponedCounter() { - myPostponedCounter.incrementAndGet(); + getContext().myPostponedCounter++; } private void decrementPostponedCounter() { Application application = ApplicationManager.getApplication(); application.assertIsDispatchThread(); - if (myPostponedCounter.decrementAndGet() == 0) { + if (--getContext().myPostponedCounter == 0) { if (application.isWriteAccessAllowed()) { doPostponedFormatting(); } @@ -175,7 +177,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { atomic(new Runnable() { @Override public void run() { - if (isDisabled() || myPostponedCounter.get() == 0 && !ApplicationManager.getApplication().isUnitTestMode()) return; + if (isDisabled() || getContext().myPostponedCounter == 0 && !ApplicationManager.getApplication().isUnitTestMode()) return; final TreeChangeEvent changeSet = (TreeChangeEvent)event.getChangeSet(myTreeAspect); if (changeSet == null) return; final PsiElement psiElement = changeSet.getRootElement().getPsi(); @@ -184,7 +186,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { final FileViewProvider viewProvider = containingFile.getViewProvider(); if (!viewProvider.isEventSystemEnabled()) return; - myUpdatedProviders.add(viewProvider); + getContext().myUpdatedProviders.add(viewProvider); for (final ASTNode node : changeSet.getChangedElements()) { final TreeChange treeChange = changeSet.getChangesByElement(node); for (final ASTNode affectedChild : treeChange.getAffectedChildren()) { @@ -221,7 +223,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { public void run() { if (isDisabled()) return; try { - FileViewProvider[] viewProviders = myUpdatedProviders.toArray(new FileViewProvider[myUpdatedProviders.size()]); + FileViewProvider[] viewProviders = getContext().myUpdatedProviders.toArray(new FileViewProvider[getContext().myUpdatedProviders.size()]); for (final FileViewProvider viewProvider : viewProviders) { doPostponedFormatting(viewProvider); } @@ -230,7 +232,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { LOG.error(e); } finally { - LOG.assertTrue(myReformatElements.isEmpty(), myReformatElements); + LOG.assertTrue(getContext().myReformatElements.isEmpty(), getContext().myReformatElements); } } }); @@ -248,7 +250,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { atomic(new Runnable() { @Override public void run() { - if (isDisabled() || check && !myUpdatedProviders.contains(viewProvider)) return; + if (isDisabled() || check && !getContext().myUpdatedProviders.contains(viewProvider)) return; try { disablePostprocessFormattingInside(new Runnable() { @@ -259,8 +261,8 @@ public class PostprocessReformattingAspect implements PomModelAspect { }); } finally { - myUpdatedProviders.remove(viewProvider); - myReformatElements.remove(viewProvider); + getContext().myUpdatedProviders.remove(viewProvider); + getContext().myReformatElements.remove(viewProvider); viewProvider.putUserData(REFORMAT_ORIGINATOR, null); } } @@ -268,7 +270,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { } public boolean isViewProviderLocked(@NotNull FileViewProvider fileViewProvider) { - return myReformatElements.containsKey(fileViewProvider); + return getContext().myReformatElements.containsKey(fileViewProvider); } public void beforeDocumentChanged(@NotNull FileViewProvider viewProvider) { @@ -292,10 +294,10 @@ public class PostprocessReformattingAspect implements PomModelAspect { LOG.assertTrue(oldIndent >= 0, "for not generated items old indentation must be defined: element=" + child + ", text=" + child.getText()); } - List<ASTNode> list = myReformatElements.get(viewProvider); + List<ASTNode> list = getContext().myReformatElements.get(viewProvider); if (list == null) { list = new ArrayList<ASTNode>(); - myReformatElements.put(viewProvider, list); + getContext().myReformatElements.put(viewProvider, list); if (STORE_REFORMAT_ORIGINATOR_STACKTRACE) { viewProvider.putUserData(REFORMAT_ORIGINATOR, new Throwable()); } @@ -304,7 +306,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { } private void doPostponedFormattingInner(@NotNull FileViewProvider key) { - final List<ASTNode> astNodes = myReformatElements.remove(key); + final List<ASTNode> astNodes = getContext().myReformatElements.remove(key); final Document document = key.getDocument(); // Sort ranges by end offsets so that we won't need any offset adjustment after reformat or reindent if (document == null) return; @@ -370,7 +372,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { String expectedPsi = treeDebugBuilder.psiToString(psi); if (!expectedPsi.equals(actualPsiTree)) { - myReformatElements.clear(); + getContext().myReformatElements.clear(); assert expectedPsi.equals(actualPsiTree) : "Refactored psi should be the same as result of parsing"; } } @@ -627,7 +629,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { } public boolean isDisabled() { - return myDisabledCounter > 0; + return getContext().myDisabledCounter > 0; } @NotNull @@ -769,6 +771,17 @@ public class PostprocessReformattingAspect implements PomModelAspect { @TestOnly public void clear() { - myReformatElements.clear(); + getContext().myReformatElements.clear(); + } + + private Context getContext() { + return myContext.get(); + } + + private static class Context { + private int myPostponedCounter = 0; + private int myDisabledCounter = 0; + private final Set<FileViewProvider> myUpdatedProviders = new HashSet<FileViewProvider>(); + private final Map<FileViewProvider, List<ASTNode>> myReformatElements = new HashMap<FileViewProvider, List<ASTNode>>(); } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java index d51ef1216a59..a9fbe1b4b988 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java @@ -58,8 +58,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; public class CodeStyleManagerImpl extends CodeStyleManager { - - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl"); + private static final Logger LOG = Logger.getInstance(CodeStyleManagerImpl.class); private static final ThreadLocal<ProcessingUnderProgressInfo> SEQUENTIAL_PROCESSING_ALLOWED = new ThreadLocal<ProcessingUnderProgressInfo>() { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemesImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemesImpl.java index 40ee4adf70f2..b12dee17e9fd 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemesImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemesImpl.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.psi.impl.source.codeStyle; import com.intellij.openapi.components.ExportableComponent; import com.intellij.openapi.components.RoamingType; +import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.options.BaseSchemeProcessor; import com.intellij.openapi.options.SchemeProcessor; import com.intellij.openapi.options.SchemesManager; @@ -44,10 +44,10 @@ public abstract class CodeStyleSchemesImpl extends CodeStyleSchemes implements E public String CURRENT_SCHEME_NAME = DEFAULT_SCHEME_NAME; private boolean myIsInitialized = false; - @NonNls static final String CODESTYLES_DIRECTORY = "codestyles"; + @NonNls static final String CODE_STYLES_DIRECTORY = "codestyles"; private final SchemesManager<CodeStyleScheme, CodeStyleSchemeImpl> mySchemesManager; - @NonNls private static final String FILE_SPEC = "$ROOT_CONFIG$/" + CODESTYLES_DIRECTORY; + @NonNls private static final String FILE_SPEC = StoragePathMacros.ROOT_CONFIG + "/" + CODE_STYLES_DIRECTORY; public CodeStyleSchemesImpl(SchemesManagerFactory schemesManagerFactory) { SchemeProcessor<CodeStyleSchemeImpl> processor = new BaseSchemeProcessor<CodeStyleSchemeImpl>() { @@ -97,6 +97,7 @@ public abstract class CodeStyleSchemesImpl extends CodeStyleSchemes implements E CURRENT_SCHEME_NAME = schemeName; } + @SuppressWarnings("ForLoopThatDoesntUseLoopVariable") @Override public CodeStyleScheme createNewScheme(String preferredName, CodeStyleScheme parentScheme) { String name; @@ -154,10 +155,6 @@ public abstract class CodeStyleSchemesImpl extends CodeStyleSchemes implements E mySchemesManager.addNewScheme(scheme, true); } - protected void removeScheme(CodeStyleScheme scheme) { - mySchemesManager.removeScheme(scheme); - } - protected void init() { if (myIsInitialized) return; myIsInitialized = true; @@ -173,6 +170,4 @@ public abstract class CodeStyleSchemesImpl extends CodeStyleSchemes implements E public SchemesManager<CodeStyleScheme, CodeStyleSchemeImpl> getSchemesManager() { return mySchemesManager; } - - } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java index 3e2acf553815..e3f4fb760fbf 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java @@ -18,8 +18,6 @@ package com.intellij.psi.impl.source.codeStyle; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.*; import com.intellij.openapi.options.SchemesManagerFactory; -import com.intellij.openapi.ui.Messages; -import com.intellij.psi.PsiBundle; import com.intellij.psi.codeStyle.CodeStyleScheme; import com.intellij.util.xmlb.Accessor; import com.intellij.util.xmlb.SerializationFilter; @@ -99,23 +97,7 @@ public class PersistableCodeStyleSchemes extends CodeStyleSchemesImpl implements @Override @NotNull public File[] getExportFiles() { - File schemesFile = new File(PathManager.getOptionsPath() + File.separator + CODE_STYLE_SCHEMES_FILE); - return new File[]{getDir(true), schemesFile}; + return new File[]{new File(PathManager.getConfigPath() + File.separator + CODE_STYLES_DIRECTORY), + new File(PathManager.getOptionsPath() + File.separator + CODE_STYLE_SCHEMES_FILE)}; } - - @Nullable - private static File getDir(boolean create) { - String directoryPath = PathManager.getConfigPath() + File.separator + CODESTYLES_DIRECTORY; - File directory = new File(directoryPath); - if (!directory.exists()) { - if (!create) return null; - if (!directory.mkdir()) { - Messages.showErrorDialog(PsiBundle.message("codestyle.cannot.save.settings.directory.cant.be.created.message", directoryPath), - PsiBundle.message("codestyle.cannot.save.settings.directory.cant.be.created.title")); - return null; - } - } - return directory; - } - } diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexState.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexState.java index 53785b7b6fda..2acd63308b48 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexState.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexState.java @@ -19,6 +19,8 @@ */ package com.intellij.psi.stubs; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -29,9 +31,9 @@ public class StubIndexState { public StubIndexState() { } - public StubIndexState(Collection<StubIndexKey<?, ?>> keys) { + public StubIndexState(@NotNull Collection<StubIndexKey<?, ?>> keys) { for (StubIndexKey key : keys) { registeredIndices.add(key.toString()); } } -}
\ No newline at end of file +} diff --git a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java index f83dcfe4788f..93921cd6c1dc 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java @@ -431,8 +431,14 @@ public abstract class BaseRefactoringProcessor implements Runnable { final Runnable prepareHelpersRunnable = new Runnable() { @Override public void run() { - for (RefactoringHelper helper : Extensions.getExtensions(RefactoringHelper.EP_NAME)) { - preparedData.put(helper, helper.prepareOperation(writableUsageInfos)); + for (final RefactoringHelper helper : Extensions.getExtensions(RefactoringHelper.EP_NAME)) { + Object operation = ApplicationManager.getApplication().runReadAction(new Computable<Object>() { + @Override + public Object compute() { + return helper.prepareOperation(writableUsageInfos); + } + }); + preparedData.put(helper, operation); } } }; diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java index a34d30dc5401..dd20f5a7d3e7 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java @@ -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. @@ -25,6 +25,7 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFrame; @@ -184,9 +185,14 @@ public class RenameProcessor extends BaseRefactoringProcessor { final Runnable runnable = new Runnable() { @Override public void run() { - for (Map.Entry<PsiElement, String> entry : renames.entrySet()) { + for (final Map.Entry<PsiElement, String> entry : renames.entrySet()) { final UsageInfo[] usages = - RenameUtil.findUsages(entry.getKey(), entry.getValue(), mySearchInComments, mySearchTextOccurrences, myAllRenames); + ApplicationManager.getApplication().runReadAction(new Computable<UsageInfo[]>() { + @Override + public UsageInfo[] compute() { + return RenameUtil.findUsages(entry.getKey(), entry.getValue(), mySearchInComments, mySearchTextOccurrences, myAllRenames); + } + }); Collections.addAll(variableUsages, usages); } } @@ -223,9 +229,14 @@ public class RenameProcessor extends BaseRefactoringProcessor { final Runnable runnable = new Runnable() { @Override public void run() { - for (final AutomaticRenamer renamer : myRenamers) { - renamer.findUsages(variableUsages, mySearchInComments, mySearchTextOccurrences, mySkippedUsages, myAllRenames); - } + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + for (final AutomaticRenamer renamer : myRenamers) { + renamer.findUsages(variableUsages, mySearchInComments, mySearchTextOccurrences, mySkippedUsages, myAllRenames); + } + } + }); } }; diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index 6fa0ed27d8c8..0f9011308533 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 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. @@ -245,7 +245,12 @@ public class VariableInplaceRenamer extends InplaceRefactoring { final Runnable runnable = new Runnable() { @Override public void run() { - renamer.findUsages(usages, false, false); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + renamer.findUsages(usages, false, false); + } + }); } }; diff --git a/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java b/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java index 102a439e11f8..1624c48f2ae5 100644 --- a/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java @@ -17,8 +17,6 @@ package com.intellij.semantic; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.project.ProjectManagerAdapter; import com.intellij.openapi.util.LowMemoryWatcher; import com.intellij.openapi.util.RecursionGuard; import com.intellij.openapi.util.RecursionManager; @@ -83,7 +81,7 @@ public class SemServiceImpl extends SemService{ }); - final LowMemoryWatcher watcher = LowMemoryWatcher.register(new Runnable() { + LowMemoryWatcher.register(new Runnable() { @Override public void run() { if (myCreatingSem.get() == 0) { @@ -91,13 +89,7 @@ public class SemServiceImpl extends SemService{ } //System.out.println("SemService cache flushed"); } - }); - ProjectManager.getInstance().addProjectManagerListener(project, new ProjectManagerAdapter() { - @Override - public void projectClosing(Project project) { - watcher.stop(); - } - }); + }, project); } private static MultiMap<SemKey, SemKey> cacheKeyHierarchy(Collection<SemKey> allKeys) { diff --git a/platform/lang-impl/src/com/intellij/tools/ToolConfigurable.java b/platform/lang-impl/src/com/intellij/tools/ToolConfigurable.java index 0f39ab8a176c..e410895b087e 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolConfigurable.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolConfigurable.java @@ -35,14 +35,18 @@ public class ToolConfigurable implements SearchableConfigurable, Configurable.No @Override public JComponent createComponent() { - myPanel = new ToolsPanel(); + if (myPanel == null) { + myPanel = new ToolsPanel(); + } return myPanel; } @Override public void apply() throws ConfigurationException { try { - myPanel.apply(); + if (myPanel != null) { + myPanel.apply(); + } } catch (IOException e) { throw new ConfigurationException(e.getMessage()); @@ -51,12 +55,14 @@ public class ToolConfigurable implements SearchableConfigurable, Configurable.No @Override public boolean isModified() { - return myPanel.isModified(); + return myPanel != null && myPanel.isModified(); } @Override public void reset() { - myPanel.reset(); + if (myPanel != null) { + myPanel.reset(); + } } @Override @@ -73,7 +79,7 @@ public class ToolConfigurable implements SearchableConfigurable, Configurable.No @Override @NotNull public String getId() { - return getHelpTopic(); + return "preferences.externalTools"; } @Override diff --git a/platform/lang-impl/src/com/intellij/tools/ToolManager.java b/platform/lang-impl/src/com/intellij/tools/ToolManager.java index 59a17bea67ed..0722090527bb 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolManager.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolManager.java @@ -17,6 +17,7 @@ package com.intellij.tools; import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.options.SchemeProcessor; import com.intellij.openapi.options.SchemesManagerFactory; import org.jetbrains.annotations.NotNull; @@ -32,7 +33,7 @@ public class ToolManager extends BaseToolManager<Tool> { @Override protected String getSchemesPath() { - return "$ROOT_CONFIG$/tools"; + return StoragePathMacros.ROOT_CONFIG + "/tools"; } @Override diff --git a/platform/lang-impl/src/com/intellij/ui/JBTableWithHintProvider.java b/platform/lang-impl/src/com/intellij/ui/JBTableWithHintProvider.java index f31de9281ea4..750331f1e49a 100644 --- a/platform/lang-impl/src/com/intellij/ui/JBTableWithHintProvider.java +++ b/platform/lang-impl/src/com/intellij/ui/JBTableWithHintProvider.java @@ -17,66 +17,53 @@ package com.intellij.ui; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.psi.PsiElement; -import com.intellij.ui.popup.PopupUpdateProcessor; +import com.intellij.ui.popup.HintUpdateSupply; import com.intellij.ui.table.JBTable; +import com.intellij.util.ObjectUtils; -import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; +import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; +/** + * @deprecated + * @see com.intellij.ui.popup.HintUpdateSupply + */ public abstract class JBTableWithHintProvider extends JBTable { - private JBPopup myHint; + + { + new HintUpdateSupply(this) { + @Override + protected PsiElement getPsiElementForHint(Object selectedValue) { + return JBTableWithHintProvider.this.getPsiElementForHint(selectedValue); + } + }; + } public JBTableWithHintProvider() { - addSelectionListener(); } protected JBTableWithHintProvider(TableModel model) { super(model); } - private void addSelectionListener() { - getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(final ListSelectionEvent e) { - if (getClientProperty(ListUtil.SELECTED_BY_MOUSE_EVENT) != Boolean.TRUE) { - - final int selected = ((ListSelectionModel)e.getSource()).getLeadSelectionIndex(); - int rowCount = getRowCount(); - if (selected == -1 || rowCount == 0) return; - - PsiElement element = getPsiElementForHint(getValueAt(Math.min(selected, rowCount -1), 0)); - if (element != null && element.isValid()) { - updateHint(element); - } - } - } - }); + public JBTableWithHintProvider(TableModel model, TableColumnModel columnModel) { + super(model, columnModel); } protected abstract PsiElement getPsiElementForHint(final Object selectedValue); - public void registerHint(final JBPopup hint) { - hideHint(); - myHint = hint; + @Deprecated + public void registerHint(JBPopup hint) { + ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).registerHint(hint); } - - public void hideHint() { - if (myHint != null && myHint.isVisible()) { - myHint.cancel(); - } - myHint = null; + @Deprecated + public void hideHint() { + ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).hideHint(); } - - public void updateHint(PsiElement element) { - if (myHint == null || !myHint.isVisible()) return; - final PopupUpdateProcessor updateProcessor = myHint.getUserData(PopupUpdateProcessor.class); - if (updateProcessor != null) { - updateProcessor.updatePopup(element); - } + @Deprecated + public void updateHint(PsiElement element) { + ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).updateHint(element); } - } diff --git a/platform/lang-impl/src/com/intellij/ui/JBTreeWithHintProvider.java b/platform/lang-impl/src/com/intellij/ui/JBTreeWithHintProvider.java index c22eeb16127f..023ed3998829 100644 --- a/platform/lang-impl/src/com/intellij/ui/JBTreeWithHintProvider.java +++ b/platform/lang-impl/src/com/intellij/ui/JBTreeWithHintProvider.java @@ -18,84 +18,58 @@ package com.intellij.ui; import com.intellij.ide.DataManager; import com.intellij.ide.dnd.aware.DnDAwareTree; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.psi.PsiElement; -import com.intellij.ui.popup.PopupUpdateProcessor; +import com.intellij.ui.popup.HintUpdateSupply; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.Nullable; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreeModel; import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; /** * @author Konstantin Bulenkov + * @deprecated + * @see com.intellij.ui.popup.HintUpdateSupply */ public class JBTreeWithHintProvider extends DnDAwareTree { - private JBPopup myHint; + { + new HintUpdateSupply(this) { + @Override + protected PsiElement getPsiElementForHint(Object selectedValue) { + return JBTreeWithHintProvider.this.getPsiElementForHint(selectedValue); + } + }; + } public JBTreeWithHintProvider() { - addSelectionListener(); } public JBTreeWithHintProvider(TreeModel treemodel) { super(treemodel); - addSelectionListener(); } public JBTreeWithHintProvider(TreeNode root) { super(root); - addSelectionListener(); - } - - private void addSelectionListener() { - addTreeSelectionListener(new TreeSelectionListener() { - @Override - public void valueChanged(final TreeSelectionEvent e) { - if (isHintBeingShown() && getClientProperty(ListUtil.SELECTED_BY_MOUSE_EVENT) != Boolean.TRUE) { - final TreePath path = getSelectionPath(); - if (path != null) { - final PsiElement psiElement = getPsiElementForHint(path.getLastPathComponent()); - if (psiElement != null && psiElement.isValid()) { - updateHint(psiElement); - } - } - } - } - }); } @Nullable protected PsiElement getPsiElementForHint(final Object selectedValue) { - // default implementation return CommonDataKeys.PSI_ELEMENT.getData(DataManager.getInstance().getDataContext(this)); } - public void registerHint(final JBPopup hint) { - hideHint(); - myHint = hint; + @Deprecated + public void registerHint(JBPopup hint) { + ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).registerHint(hint); } + @Deprecated public void hideHint() { - if (isHintBeingShown()) { - myHint.cancel(); - } - - myHint = null; + ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).hideHint(); } + @Deprecated public void updateHint(PsiElement element) { - if (!isHintBeingShown()) return; - - final PopupUpdateProcessor updateProcessor = myHint.getUserData(PopupUpdateProcessor.class); - if (updateProcessor != null) { - updateProcessor.updatePopup(element); - } - } - - private boolean isHintBeingShown() { - return myHint != null && myHint.isVisible(); + ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).updateHint(element); } } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/PopupUpdateProcessor.java b/platform/lang-impl/src/com/intellij/ui/popup/PopupUpdateProcessor.java index f02111c5ee11..d5b5bdf09194 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/PopupUpdateProcessor.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/PopupUpdateProcessor.java @@ -24,10 +24,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.psi.PsiElement; -import com.intellij.ui.JBListWithHintProvider; -import com.intellij.ui.JBTableWithHintProvider; -import com.intellij.ui.JBTreeWithHintProvider; +import javax.swing.*; import java.awt.*; /** @@ -39,7 +37,6 @@ public abstract class PopupUpdateProcessor extends PopupUpdateProcessorBase { protected PopupUpdateProcessor(Project project) { myProject = project; - } @Override @@ -71,14 +68,10 @@ public abstract class PopupUpdateProcessor extends PopupUpdateProcessorBase { if (fromQuickSearch) { ChooseByNameBase.JPanelProvider panelProvider = (ChooseByNameBase.JPanelProvider)focusedComponent.getParent(); panelProvider.registerHint(windowEvent.asPopup()); - } else if (focusedComponent != null) { - if (focusedComponent instanceof JBListWithHintProvider) { - ((JBListWithHintProvider)focusedComponent).registerHint(windowEvent.asPopup()); - } else if (focusedComponent instanceof JBTableWithHintProvider) { - ((JBTableWithHintProvider)focusedComponent).registerHint(windowEvent.asPopup()); - } else if (focusedComponent instanceof JBTreeWithHintProvider) { - ((JBTreeWithHintProvider)focusedComponent).registerHint(windowEvent.asPopup()); - } + } + else if (focusedComponent instanceof JComponent) { + HintUpdateSupply supply = HintUpdateSupply.getSupply((JComponent)focusedComponent); + if (supply != null) supply.registerHint(windowEvent.asPopup()); } } } diff --git a/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java b/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java index 4dee56707ae0..eb06160d4280 100644 --- a/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java +++ b/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java @@ -167,7 +167,9 @@ public class UsageViewUtil { int offset = info.getNavigationOffset(); VirtualFile file = info.getVirtualFile(); Project project = info.getProject(); - FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file, offset), requestFocus); + if (file != null) { + FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file, offset), requestFocus); + } } public static Set<UsageInfo> getNotExcludedUsageInfos(final UsageView usageView) { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index da85132806e5..019b3172817f 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1727,7 +1727,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { } private static void cleanFileContent(@NotNull FileContentImpl fc, PsiFile psiFile) { - if (psiFile != null) psiFile.putUserData(PsiFileImpl.BUILDING_STUB, false); + if (psiFile != null) psiFile.putUserData(PsiFileImpl.BUILDING_STUB, null); fc.putUserData(IndexingDataKeys.PSI_FILE, null); } diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java index fcbaa21f330b..f66982282fa0 100644 --- a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java +++ b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java @@ -419,7 +419,7 @@ public class ManagePackagesDialog extends DialogWrapper { else { myFilteredOut.add(repoPackage); } - if (StringUtil.equals(packageName, filter)) toSelect = repoPackage; + if (StringUtil.equalsIgnoreCase(packageName, filter)) toSelect = repoPackage; } filter(filtered, toSelect); } |