diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java index 5c7be0535dca..14ce3fe14192 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java @@ -182,7 +182,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { } selectedForRecompilation.add(file); if (pathsToRecompile == null || !pathsToRecompile.contains(fileId)) { - addSourceForRecompilation(projectId, file, null); + loadInfoAndAddSourceForRecompilation(projectId, file); } } else { @@ -286,7 +286,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { throws IOException { final Project project = context.getProject(); final int projectId = getProjectId(project); - if (successfullyCompiled.size() > 0) { + if (!successfullyCompiled.isEmpty()) { final LocalFileSystem lfs = LocalFileSystem.getInstance(); final IOException[] exceptions = {null}; // need read action here to ensure that no modifications were made to VFS while updating file attributes @@ -354,7 +354,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { } } removeSourceForRecompilation(projectId, Math.abs(getFileId(file))); - if ((fileStamp > compilationStartStamp && !((CompileContextEx)context).isGenerated(file)) || forceRecompile.contains(file)) { + if (fileStamp > compilationStartStamp && !((CompileContextEx)context).isGenerated(file) || forceRecompile.contains(file)) { // changes were made during compilation, need to re-schedule compilation // it is important to invoke removeSourceForRecompilation() before this call to make sure // the corresponding output paths will be scheduled for deletion @@ -377,7 +377,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { public void run() { for (VirtualFile file : filesToRecompile) { if (file.isValid()) { - addSourceForRecompilation(projectId, file, null); + loadInfoAndAddSourceForRecompilation(projectId, file); } } } @@ -903,7 +903,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { // made public for tests public void scanSourceContent(final ProjectRef projRef, final Collection roots, final int totalRootCount, final boolean isNewRoots) { - if (roots.size() == 0) { + if (roots.isEmpty()) { return; } final int projectId = getProjectId(projRef.get()); @@ -1029,7 +1029,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { final String srcPath = outputInfo.getSourceFilePath(); final VirtualFile srcFile = srcPath != null? LocalFileSystem.getInstance().findFileByPath(srcPath) : null; if (srcFile != null) { - addSourceForRecompilation(projectId, srcFile, null); + loadInfoAndAddSourceForRecompilation(projectId, srcFile); } } } @@ -1317,7 +1317,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { processRecursively(file, false, new FileProcessor() { public void execute(final VirtualFile file) { if (isCompilable(file)) { - addSourceForRecompilation(projectId, file, null); + loadInfoAndAddSourceForRecompilation(projectId, file); } } @@ -1335,7 +1335,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { if (belongsToIntermediateSources(file, project)) { processRecursively(file, false, new FileProcessor() { public void execute(final VirtualFile file) { - addSourceForRecompilation(projectId, file, null); + loadInfoAndAddSourceForRecompilation(projectId, file); } }); } @@ -1356,9 +1356,10 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { return false; } - private void addSourceForRecompilation(final int projectId, final VirtualFile srcFile, @Nullable final SourceFileInfo preloadedInfo) { - final SourceFileInfo srcInfo = preloadedInfo != null? preloadedInfo : loadSourceInfo(srcFile); - + private void loadInfoAndAddSourceForRecompilation(final int projectId, final VirtualFile srcFile) { + addSourceForRecompilation(projectId, srcFile, loadSourceInfo(srcFile)); + } + private void addSourceForRecompilation(final int projectId, final VirtualFile srcFile, @Nullable final SourceFileInfo srcInfo) { final boolean alreadyMarked; synchronized (myDataLock) { TIntHashSet set = mySourcesToRecompile.get(projectId); diff --git a/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java b/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java index 00e2bb8433c4..8e94a2079f27 100644 --- a/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java +++ b/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java @@ -12,7 +12,6 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -109,14 +108,7 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase { MyClassLoader classLoader = new MyClassLoader(getClass().getClassLoader()); for (File file : files) { final String fileName = file.getName(); - FileInputStream stream = new FileInputStream(file); - byte[] content; - try { - content = FileUtil.adaptiveLoadBytes(stream); - } - finally { - stream.close(); - } + byte[] content = FileUtil.loadFileBytes(file); ClassReader reader = new ClassReader(content, 0, content.length); ClassWriter writer = new PsiClassWriter(myFixture.getProject(), false); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CollectHighlightsUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CollectHighlightsUtil.java index 59f11b128a57..9a7dcfa37da8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CollectHighlightsUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CollectHighlightsUtil.java @@ -146,8 +146,10 @@ public class CollectHighlightsUtil { LOG.assertTrue(commonParent != null); LOG.assertTrue(commonParent.getTextRange() != null); - while (commonParent.getParent() != null && commonParent.getTextRange().equals(commonParent.getParent().getTextRange())) { - commonParent = commonParent.getParent(); + PsiElement parent = commonParent.getParent(); + while (parent != null && commonParent.getTextRange().equals(parent.getTextRange())) { + commonParent = parent; + parent = parent.getParent(); } return commonParent; } 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 c9c8549126d8..7c020d84aa7d 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 @@ -190,11 +190,11 @@ class DaemonListeners implements Disposable { connection.subscribe(DumbService.DUMB_MODE, new DumbService.DumbModeListener() { public void enteredDumbMode() { - stopDaemon(true); + myDaemonCodeAnalyzer.restart(); } public void exitDumbMode() { - stopDaemon(true); + myDaemonCodeAnalyzer.restart(); } }); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java index d238a586f68d..cee89801ef82 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java @@ -43,12 +43,13 @@ public class Divider { @NotNull TextRange range, @NotNull List inside, @NotNull List outside, - @NotNull HighlightLevelUtil.AnalysisLevel level) { + @NotNull HighlightLevelUtil.AnalysisLevel level, + boolean includeParents) { final FileViewProvider viewProvider = file.getViewProvider(); for (Language language : viewProvider.getLanguages()) { final PsiFile psiRoot = viewProvider.getPsi(language); if (HighlightLevelUtil.shouldAnalyse(psiRoot, level)) { - divideInsideAndOutside(psiRoot, startOffset, endOffset, range, inside, outside); + divideInsideAndOutside(psiRoot, startOffset, endOffset, range, inside, outside, includeParents); } } } @@ -58,8 +59,8 @@ public class Divider { int endOffset, @NotNull TextRange range, @NotNull List inside, - @NotNull List outside - ) { + @NotNull List outside, + boolean includeParents) { final int currentOffset = root.getTextRange().getStartOffset(); final Condition[] filters = Extensions.getExtensions(CollectHighlightsUtil.EP_NAME); @@ -122,5 +123,15 @@ public class Divider { child = PsiUtilBase.NULL_PSI_ELEMENT; } } + + if (includeParents) { + PsiElement parent = !outside.isEmpty() ? outside.get(outside.size() - 1) : + !inside.isEmpty() ? inside.get(inside.size() - 1) : + CollectHighlightsUtil.findCommonParent(root, startOffset, endOffset); + while (parent != null && parent != root) { + parent = parent.getParent(); + if (parent != null) outside.add(parent); + } + } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java index f225977ba317..f9df08d33690 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java @@ -177,7 +177,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP final List outside = new ArrayList(); try { Divider.divideInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, inside, outside, - HighlightLevelUtil.AnalysisLevel.HIGHLIGHT); + HighlightLevelUtil.AnalysisLevel.HIGHLIGHT,false); final Set injected = new THashSet(); getInjectedPsiFiles(inside, outside, progress, injected); 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 712cf8243048..ab001ac96da3 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 @@ -196,9 +196,9 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass ArrayList inside = new ArrayList(); ArrayList outside = new ArrayList(); Divider.divideInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, inside, outside, - HighlightLevelUtil.AnalysisLevel.HIGHLIGHT_AND_INSPECT); + HighlightLevelUtil.AnalysisLevel.HIGHLIGHT_AND_INSPECT,true); - setProgressLimit(1L * tools.size() *2/** (inside.size() + outside.size())*/); + setProgressLimit(1L * tools.size() * 2); final LocalInspectionToolSession session = new LocalInspectionToolSession(myFile, myStartOffset, myEndOffset); List> init = new ArrayList>(); diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/GotoInspectionModel.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/GotoInspectionModel.java new file mode 100644 index 000000000000..f3acc5d8ab8f --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/GotoInspectionModel.java @@ -0,0 +1,241 @@ +/* + * Copyright 2000-2010 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.codeInspection.InspectionProfileEntry; +import com.intellij.codeInspection.ex.InspectionProfileImpl; +import com.intellij.codeInspection.ex.ScopeToolState; +import com.intellij.ide.IdeBundle; +import com.intellij.ide.util.gotoByName.SimpleChooseByNameModel; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.profile.codeInspection.InspectionProfileManager; +import com.intellij.util.ArrayUtil; +import org.apache.oro.text.regex.*; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.*; + +/** + * @author Konstantin Bulenkov + */ +public class GotoInspectionModel extends SimpleChooseByNameModel {//implements CustomMatcherModel { + private String myPattern; + + private Pattern myCompiledPattern; + private final PatternMatcher myMatcher = new Perl5Matcher(); + private final Map myToolNames = new HashMap(); + private final Map> myGroupNames = new HashMap>(); + private final Map myToolShortNames = new HashMap(); + private String[] myNames; + private final ListCellRenderer myListCellRenderer = new InspectionListCellRenderer(); + + + public GotoInspectionModel(Project project) { + super(project, IdeBundle.message("prompt.goto.inspection.enter.name"), null); //TODO help ID + final InspectionProfileImpl rootProfile = (InspectionProfileImpl)InspectionProfileManager.getInstance().getRootProfile(); + for (ScopeToolState state : rootProfile.getAllTools()) { + final InspectionProfileEntry tool = state.getTool(); + myToolNames.put(tool.getDisplayName(), tool); + final String groupName = tool.getGroupDisplayName(); + Set toolsInGroup = myGroupNames.get(groupName); + if (toolsInGroup == null) { + toolsInGroup = new HashSet(); + myGroupNames.put(groupName, toolsInGroup); + } + toolsInGroup.add(tool); + myToolShortNames.put(tool.getShortName(), tool); + } + + final Set nameIds = new HashSet(); + nameIds.addAll(myToolNames.keySet()); + nameIds.addAll(myGroupNames.keySet()); + //nameIds.addAll(myToolShortNames.keySet()); + myNames = ArrayUtil.toStringArray(nameIds); + } + + public ListCellRenderer getListCellRenderer() { + return myListCellRenderer; + } + + public String[] getNames() { + return myNames; + } + + public Object[] getElementsByName(final String id, final String pattern) { + final Set result = new HashSet(); + InspectionProfileEntry e = myToolNames.get(id); + if (e != null) { + result.add(e); + } + e = myToolShortNames.get(id); + if (e != null) { + result.add(e); + } + final Set entries = myGroupNames.get(id); + if (entries != null) { + result.addAll(entries); + } + return result.toArray(new InspectionProfileEntry[result.size()]); + } + + public String getElementName(final Object element) { + if (element instanceof InspectionProfileEntry) { + final InspectionProfileEntry entry = (InspectionProfileEntry)element; + return entry.getDisplayName() + " " + entry.getGroupDisplayName(); + } + return null; + } + + private List findEntries(String name) { + final List result = new ArrayList(); + InspectionProfileEntry e = myToolNames.get(name); + if (e != null) { + result.add(e); + } + //e = myToolShortNames.get(name); + //if (e != null) { + // result.add(e); + //} + final Set entrySet = myGroupNames.get(name); + if (entrySet != null) { + result.addAll(entrySet); + } + return result; + } + + public boolean matches(@NotNull final String name, @NotNull final String pattern) { + for (InspectionProfileEntry entry : findEntries(name)) { + final String toolName = entry.getDisplayName(); + final String id = entry.getShortName(); + final String group = entry.getGroupDisplayName(); + final Pattern compiledPattern = getPattern(pattern); + if (myMatcher.matches(toolName, compiledPattern) + || myMatcher.matches(id, compiledPattern) + || myMatcher.matches(group, compiledPattern)) { + return true; + } + } + + return false; + } + + @NotNull + private Pattern getPattern(String pattern) { + if (!Comparing.strEqual(pattern, myPattern)) { + myCompiledPattern = null; + myPattern = pattern; + } + if (myCompiledPattern == null) { + boolean allowToLower = true; + final int eol = pattern.indexOf('\n'); + if (eol != -1) { + pattern = pattern.substring(0, eol); + } + if (pattern.length() >= 80) { + pattern = pattern.substring(0, 80); + } + + final @NonNls StringBuffer buffer = new StringBuffer(); + + if (containsOnlyUppercaseLetters(pattern)) { + allowToLower = false; + } + + if (allowToLower) { + buffer.append(".*"); + } + + boolean firstIdentifierLetter = true; + for (int i = 0; i < pattern.length(); i++) { + final char c = pattern.charAt(i); + if (Character.isLetterOrDigit(c)) { + // This logic allows to use uppercase letters only to catch the name like PDM for PsiDocumentManager + if (Character.isUpperCase(c) || Character.isDigit(c)) { + + if (!firstIdentifierLetter) { + buffer.append("[^A-Z]*"); + } + + buffer.append("["); + buffer.append(c); + if (allowToLower || i == 0) { + buffer.append('|'); + buffer.append(Character.toLowerCase(c)); + } + buffer.append("]"); + } + else if (Character.isLowerCase(c)) { + buffer.append('['); + buffer.append(c); + buffer.append('|'); + buffer.append(Character.toUpperCase(c)); + buffer.append(']'); + } + else { + buffer.append(c); + } + + firstIdentifierLetter = false; + } + else if (c == '*') { + buffer.append(".*"); + firstIdentifierLetter = true; + } + else if (c == '.') { + buffer.append("\\."); + firstIdentifierLetter = true; + } + else if (c == ' ') { + buffer.append("[^A-Z]*\\ "); + firstIdentifierLetter = true; + } + else { + firstIdentifierLetter = true; + // for standard RegExp engine + // buffer.append("\\u"); + // buffer.append(Integer.toHexString(c + 0x20000).substring(1)); + + // for OROMATCHER RegExp engine + buffer.append("\\x"); + buffer.append(Integer.toHexString(c + 0x20000).substring(3)); + } + } + + buffer.append(".*"); + + + try { + myCompiledPattern = new Perl5Compiler().compile(buffer.toString()); + } + catch (MalformedPatternException e) { + //do nothing + } + } + + return myCompiledPattern; + } + + private static boolean containsOnlyUppercaseLetters(String s) { + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c != '*' && c != ' ' && !Character.isUpperCase(c)) return false; + } + return true; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/InspectionListCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/InspectionListCellRenderer.java new file mode 100644 index 000000000000..d5319d092397 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/InspectionListCellRenderer.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2010 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.codeInspection.InspectionProfileEntry; +import com.intellij.util.ui.EmptyIcon; +import com.intellij.util.ui.UIUtil; + +import javax.swing.*; +import java.awt.*; + +/** +* @author Konstantin Bulenkov +*/ +@SuppressWarnings({"GtkPreferredJComboBoxRenderer"}) +public class InspectionListCellRenderer extends DefaultListCellRenderer { + private static final EmptyIcon EMPTY_ICON = new EmptyIcon(18, 18); + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean sel, boolean focus) { + final JPanel panel = new JPanel(new BorderLayout()); + panel.setOpaque(true); + + final Color bg = sel ? UIUtil.getListSelectionBackground() : UIUtil.getListBackground(); + panel.setBackground(bg); + + if (value instanceof InspectionProfileEntry) { + final InspectionProfileEntry tool = (InspectionProfileEntry)value; + final Color fg = sel ? UIUtil.getListSelectionForeground() : UIUtil.getListForeground(); + + final JLabel label = new JLabel(" " + tool.getDisplayName()); + panel.add(label, BorderLayout.WEST); + + final JLabel groupLabel = new JLabel(tool.getGroupDisplayName() + " ", EMPTY_ICON, LEFT); + groupLabel.setBackground(bg); + groupLabel.setForeground(fg); + panel.add(groupLabel, BorderLayout.EAST); + } + + return panel; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java new file mode 100644 index 000000000000..cacec609a9a9 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java @@ -0,0 +1,141 @@ +/* + * Copyright 2000-2010 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.analysis.AnalysisScope; +import com.intellij.analysis.AnalysisScopeBundle; +import com.intellij.analysis.AnalysisUIOptions; +import com.intellij.analysis.BaseAnalysisActionDialog; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.codeInspection.InspectionsBundle; +import com.intellij.codeInspection.ex.GlobalInspectionContextImpl; +import com.intellij.codeInspection.ex.InspectionManagerEx; +import com.intellij.codeInspection.ex.InspectionProfileImpl; +import com.intellij.featureStatistics.FeatureUsageTracker; +import com.intellij.ide.IdeBundle; +import com.intellij.ide.actions.GotoActionBase; +import com.intellij.ide.util.gotoByName.ChooseByNamePopup; +import com.intellij.ide.util.gotoByName.ChooseByNamePopupComponent; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; +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 org.jdom.Element; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.Arrays; + +/** + * @author Konstantin Bulenkov + */ +public class RunInspectionAction extends GotoActionBase { + public RunInspectionAction() { + getTemplatePresentation().setText(IdeBundle.message("goto.inspection.action.text")); + } + + @Override + protected void gotoActionPerformed(final AnActionEvent e) { + final Project project = e.getData(PlatformDataKeys.PROJECT); + final Component component = e.getData(PlatformDataKeys.CONTEXT_COMPONENT); + final PsiElement psiElement = LangDataKeys.PSI_ELEMENT.getData(e.getDataContext()); + final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(e.getDataContext()); + final VirtualFile virtualFile = LangDataKeys.VIRTUAL_FILE.getData(e.getDataContext()); + if (project == null || virtualFile == null) return; + FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.inspection"); + + final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, new GotoInspectionModel(project), getPsiContext(e)); + popup.setSearchInAnyPlace(true); + popup.invoke(new ChooseByNamePopupComponent.Callback() { + public void onClose() { + if (RunInspectionAction.class.equals(myInAction)) { + myInAction = null; + } + } + + public void elementChosen(Object element) { + final InspectionProfileEntry profileEntry = (InspectionProfileEntry)element; + runInspection(project, profileEntry, virtualFile, psiElement, psiFile); + } + }, ModalityState.current(), true); + } + + private static void runInspection(@NotNull Project project, + @NotNull InspectionProfileEntry profileEntry, + @NotNull VirtualFile virtualFile, + PsiElement psiElement, PsiFile psiFile) { + final String shortName = profileEntry.getShortName(); + final InspectionManagerEx managerEx = (InspectionManagerEx)InspectionManagerEx.getInstance(project); + final Module module = ModuleUtil.findModuleForFile(virtualFile, project); + + AnalysisScope analysisScope = null; + if (psiFile != null) { + analysisScope = new AnalysisScope(psiFile); + } else { + if (virtualFile.isDirectory()) { + final PsiDirectory psiDirectory = PsiManager.getInstance(project).findDirectory(virtualFile); + if (psiDirectory != null) { + analysisScope = new AnalysisScope(psiDirectory); + } + } + if (analysisScope == null) { + analysisScope = new AnalysisScope(project, Arrays.asList(virtualFile)); + } + } + final BaseAnalysisActionDialog dlg = new BaseAnalysisActionDialog( + AnalysisScopeBundle.message("specify.analysis.scope", InspectionsBundle.message("inspection.action.title")), + AnalysisScopeBundle.message("analysis.scope.title", InspectionsBundle.message("inspection.action.noun")), + project, + analysisScope, + module != null ? module.getName() : null, + true, + AnalysisUIOptions.getInstance(project), + psiElement); + AnalysisScope scope = analysisScope; + dlg.show(); + if (!dlg.isOK()) return; + final AnalysisUIOptions uiOptions = AnalysisUIOptions.getInstance(project); + scope = dlg.getScope(uiOptions, scope, project, module); + + final InspectionProfileImpl profile = new InspectionProfileImpl(profileEntry.getDisplayName()); + final InspectionProfileImpl model = (InspectionProfileImpl)profile.getModifiableModel(); + final InspectionProfileEntry[] profileEntries = model.getInspectionTools(null); + for (InspectionProfileEntry entry : profileEntries) { + model.disableTool(entry.getShortName()); + } + model.enableTool(shortName); + try { + Element element = new Element("toCopy"); + profileEntry.writeSettings(element); + model.getInspectionTool(shortName).readSettings(element); + } + catch (Exception e) { + //skip + } + model.setEditable(profileEntry.getDisplayName()); + final GlobalInspectionContextImpl inspectionContext = managerEx.createNewGlobalContext(false); + inspectionContext.setExternalProfile(model); + inspectionContext.doInspections(scope, managerEx); + } +} 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 11a5f9aa547c..5da50d327f80 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 @@ -81,6 +81,7 @@ public abstract class ChooseByNameBase { protected final String myInitialText; private boolean myPreselectInitialText; private final Reference myContext; + private boolean mySearchInAnyPlace = false; protected Component myPreviouslyFocusedComponent; @@ -166,6 +167,14 @@ public abstract class ChooseByNameBase { myShowListAfterCompletionKeyStroke = showListAfterCompletionKeyStroke; } + public boolean isSearchInAnyPlace() { + return mySearchInAnyPlace; + } + + public void setSearchInAnyPlace(boolean searchInAnyPlace) { + mySearchInAnyPlace = searchInAnyPlace; + } + /** * Set tool area. The method may be called only before invoke. * @@ -1196,6 +1205,10 @@ public abstract class ChooseByNameBase { String namePattern = getNamePattern(pattern); String qualifierPattern = getQualifierPattern(pattern); + if (isSearchInAnyPlace() && namePattern.trim().length() > 0) { + namePattern = "*" + namePattern + "*"; + } + boolean empty = namePattern.length() == 0 || namePattern.equals("@"); // TODO[yole]: remove implicit dependency if (empty && !canShowListForEmptyPattern()) return; diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/SimpleChooseByNameModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/SimpleChooseByNameModel.java new file mode 100644 index 000000000000..fa7e20e05fd2 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/SimpleChooseByNameModel.java @@ -0,0 +1,106 @@ +/* + * Copyright 2000-2010 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.util.gotoByName; + +import com.intellij.codeInspection.InspectionsBundle; +import com.intellij.openapi.project.Project; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Konstantin Bulenkov + */ +public abstract class SimpleChooseByNameModel implements ChooseByNameModel { + private final Project myProject; + private final String myPrompt; + private final String myHelpId; + + protected SimpleChooseByNameModel(@NotNull Project project, @NotNull String prompt, @Nullable String helpId) { + myProject = project; + myPrompt = prompt; + myHelpId = helpId; + } + + public abstract String[] getNames(); + + protected abstract Object[] getElementsByName(String name, String pattern); + + + public Project getProject() { + return myProject; + } + + @Override + public String getPromptText() { + return myPrompt; + } + + @Override + public String getNotInMessage() { + return InspectionsBundle.message("nothing.found"); + } + + @Override + public String getNotFoundMessage() { + return InspectionsBundle.message("nothing.found"); + } + + @Override + public String getCheckBoxName() { + return null; + } + + @Override + public char getCheckBoxMnemonic() { + return 0; + } + + @Override + public boolean loadInitialCheckBoxState() { + return false; + } + + @Override + public void saveInitialCheckBoxState(boolean state) { + } + + @Override + public String[] getNames(boolean checkBoxState) { + return getNames(); + } + + @Override + public Object[] getElementsByName(String name, boolean checkBoxState, String pattern) { + return getElementsByName(name, pattern); + } + + @NotNull + @Override + public String[] getSeparators() { + return ArrayUtil.EMPTY_STRING_ARRAY; + } + + @Override + public String getFullName(Object element) { + return getElementName(element); + } + + @Override + public String getHelpId() { + return myHelpId; + } +} diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java index 3e6c16b5e48d..7609188eb1ad 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java @@ -185,7 +185,7 @@ public class VfsUtil { public static VirtualFile copyFile(Object requestor, @NotNull VirtualFile file, @NotNull VirtualFile toDir, @NotNull @NonNls String newName) throws IOException { final VirtualFile newChild = toDir.createChildData(requestor, newName); - // [jeka] TODO: to be duscussed if the copy should have the same timestamp as the original + // [jeka] TODO: to be discussed if the copy should have the same timestamp as the original //OutputStream out = newChild.getOutputStream(requestor, -1, file.getActualTimeStamp()); newChild.setBinaryContent(file.contentsToByteArray()); return newChild; diff --git a/platform/platform-api/src/com/intellij/ui/content/Content.java b/platform/platform-api/src/com/intellij/ui/content/Content.java index 56cb366cabcf..e0b134bcccd6 100644 --- a/platform/platform-api/src/com/intellij/ui/content/Content.java +++ b/platform/platform-api/src/com/intellij/ui/content/Content.java @@ -63,7 +63,7 @@ public interface Content extends UserDataHolder, ComponentContainer { Disposable getDisposer(); /** - * @param disposer a Disposable object whoes dispose() method will be invoked upon this content release. + * @param disposer a Disposable object which dispose() method will be invoked upon this content release. */ void setDisposer(Disposable disposer); diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index ee083e9f7fde..abae7954d89e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -753,7 +753,7 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application return; } - LOG.assertTrue(myTestModeFlag || !Thread.holdsLock(PsiLock.LOCK), "Thread must not hold PsiLock while performing readAction"); + LOG.assertTrue(!Thread.holdsLock(PsiLock.LOCK), "Thread must not hold PsiLock while performing readAction"); try { myActionsLock.readLock().acquire(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/MappingUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/MappingUtil.java index 3385fb034f5d..be229c854237 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/MappingUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/MappingUtil.java @@ -65,9 +65,6 @@ public class MappingUtil { continue; } if (cacheEntry.startOffset > offset) { - if (start == end) { - return start - 1; - } end = i - 1; continue; } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java b/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java index a16ddd779961..426c3dc24998 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java @@ -239,7 +239,8 @@ class CacheUpdateRunner { } private static Runnable getProcessWrapper(final Runnable process) { - return ApplicationManager.getApplication().isWriteAccessAllowed() ? new Runnable() { + // launching thread will hold read access for workers + return ApplicationManager.getApplication().isReadAccessAllowed() ? new Runnable() { @Override public void run() { boolean old = ApplicationImpl.setExceptionalThreadWithReadAccessFlag(true); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java index bb914dcb93d2..6a2722fde9c9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java @@ -549,10 +549,6 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { return stream; } - public void restoreContent(VirtualFile file, Object requestor, final long modStamp, final long timeStamp) { - - } - public int acquireContent(VirtualFile file) { return myRecords.acquireFileContent(getFileId(file)); } diff --git a/platform/platform-resources-en/src/messages/FeatureStatisticsBundle.properties b/platform/platform-resources-en/src/messages/FeatureStatisticsBundle.properties index ded554dd55f7..72bb568e217b 100644 --- a/platform/platform-resources-en/src/messages/FeatureStatisticsBundle.properties +++ b/platform/platform-resources-en/src/messages/FeatureStatisticsBundle.properties @@ -106,6 +106,7 @@ group.tools=Tools support navigation.popup.action=Go to action navigation.goto.usages=Show usages +navigation.goto.inspection=Go to inspection # suppress inspection "UnusedProperty" editing.completion.completeStatement=Complete Statement from Code Completion codeassists.highlight.implements=Highlight implementing or overriding members diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 9d3e74a5e995..162db4d696b3 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1069,3 +1069,6 @@ browsers.settings=Web Browsers updates.check.period.on.exit=On every exit use.sun.jdk.prompt=Java version is not supported, please use Sun/Oracle JDK rather than OpenJDK +prompt.goto.inspection.enter.name=Enter inspection name: +goto.inspection.action.text=&Run Inspection by Name... +label.no.inspections.found=No inspections found diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index a2fd36b34f3c..294a9c8ab730 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -626,3 +626,4 @@ detach.library.roots.quickfix.name=Detach unused library roots inspection.javadoc.problem.pointing.to.itself=Javadoc pointing to itself inspection.redirect.template=Injected element has problem: {0} (in {3}). +nothing.found=Nothing found diff --git a/platform/platform-resources-en/src/tips/GoToInspection.html b/platform/platform-resources-en/src/tips/GoToInspection.html new file mode 100644 index 000000000000..87cb6e66b243 --- /dev/null +++ b/platform/platform-resources-en/src/tips/GoToInspection.html @@ -0,0 +1,14 @@ + + + + + + +
To quickly find and run an inspection press + &shortcut:RunInspection; + (Go To | Inspection on the main + menu) and start typing the name of the inspection or its group. Choose the desired inspection from the suggestion list and + then select a desired scope. +
+ + diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml index 1e86171aa14e..b075de2d9e48 100644 --- a/platform/platform-resources/src/idea/Keymap_Default.xml +++ b/platform/platform-resources/src/idea/Keymap_Default.xml @@ -215,6 +215,9 @@ + + + diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 0c163e2eb78a..9c08ef8d9014 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -698,6 +698,11 @@ + + + + + diff --git a/platform/platform-resources/src/idea/PlatformLangActionManager.xml b/platform/platform-resources/src/idea/PlatformLangActionManager.xml index 459954d352c8..4abc5d16a1a5 100644 --- a/platform/platform-resources/src/idea/PlatformLangActionManager.xml +++ b/platform/platform-resources/src/idea/PlatformLangActionManager.xml @@ -53,10 +53,11 @@ + - \ No newline at end of file + diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index 4d6961875bf2..d1a823fd425b 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -157,6 +157,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra } }; myRootPanel = new MyPanel(myTree); + Disposer.register(this, myRootPanel); myModelTracker = new UsageModelTracker(project); Disposer.register(this, myModelTracker); @@ -798,7 +799,6 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra ToolTipManager.sharedInstance().unregisterComponent(myTree); myModelTracker.removeListener(this); myUpdateAlarm.cancelAllRequests(); - myRootPanel.dispose(); if (myUsagePreviewPanel != null) { UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS = ((Splitter)myUsagePreviewPanel.getParent()).getProportion(); myUsagePreviewPanel = null; @@ -1061,7 +1061,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra return myModel.areTargetsValid(); } - private class MyPanel extends JPanel implements TypeSafeDataProvider, OccurenceNavigator { + private class MyPanel extends JPanel implements TypeSafeDataProvider, OccurenceNavigator,Disposable { @Nullable private OccurenceNavigatorSupport mySupport; private MyPanel(JTree tree) { @@ -1081,7 +1081,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra }; } - private void dispose() { + public void dispose() { mySupport = null; } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointManager.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointManager.java index 75b8e47bf94b..d9bb56fd71f3 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointManager.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointManager.java @@ -50,6 +50,8 @@ public interface XBreakpointManager { XLineBreakpoint

findBreakpointAtLine(@NotNull XLineBreakpointType

type, @NotNull VirtualFile file, int line); + boolean isDefaultBreakpoint(@NotNull XBreakpoint breakpoint); + , P extends XBreakpointProperties> void addBreakpointListener(@NotNull XBreakpointType type, @NotNull XBreakpointListener listener); diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java index cdcc335c128f..2ed9f463dc4e 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java @@ -39,8 +39,9 @@ import java.util.Comparator; * <extensions defaultExtensionNs="com.intellij">
*   <xdebugger.breakpointType implementation="qualified-class-name"/>
* </extensions> + *

* - * Use this class only for breakpoints like an exception breakpoints in Java. If a breakpoint will be put on some line in a file use + * Use this class only for breakpoints like exception breakpoints in Java. If a breakpoint will be put on some line in a file use * {@link XLineBreakpointType} instead * * @author nik @@ -145,6 +146,17 @@ public abstract class XBreakpointType, P extends XBreak return null; } + /** + * Returns properties of the default breakpoint. The default breakpoints cannot be deleted and is always shown on top of the breakpoints + * list in the dialog. It is disabled by default. + * + * @return a default breakpoint properties or {@code null} if default breakpoint isn't supported + */ + @Nullable + public P createDefaultBreakpointProperties() { + return null; + } + @Nullable @NonNls public String getBreakpointsDialogHelpTopic() { return null; diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java index d0df07be9aeb..c867184bfa0a 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java @@ -39,7 +39,7 @@ import java.util.Collections; * <extensions defaultExtensionNs="com.intellij">
*   <xdebugger.breakpointType implementation="qualified-class-name"/>
* </extensions> - * + *

* In order to support actual setting breakpoints in a debugging process create a {@link XBreakpointHandler} implementation and return it * from {@link com.intellij.xdebugger.XDebugProcess#getBreakpointHandlers()} method * @@ -85,6 +85,14 @@ public abstract class XLineBreakpointType

exten return XDebuggerUtil.getInstance().getDefaultLineBreakpointComparator(); } + /** + * Default line breakpoints cannot be supported + */ + @Override + public final P createDefaultBreakpointProperties() { + return null; + } + public List getAdditionalPopupMenuActions(@NotNull XLineBreakpoint

breakpoint, @Nullable XDebugSession currentSession) { return Collections.emptyList(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActions.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActions.java index 0a6926167058..7462a6146121 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActions.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActions.java @@ -44,6 +44,7 @@ public interface XDebuggerActions { @NonNls String VARIABLES_TREE_POPUP_GROUP = "XDebugger.Variables.Tree.Popup"; @NonNls String WATCHES_TREE_POPUP_GROUP = "XDebugger.Watches.Tree.Popup"; @NonNls String WATCHES_TREE_TOOLBAR_GROUP = "XDebugger.Watches.Tree.Toolbar"; + @NonNls String VALUE_HINT_TREE_POPUP_GROUP = "XDebugger.Value.Hint.Tree.Popup"; @NonNls String ADD_TO_WATCH = "Debugger.AddToWatch"; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java index ccae800efd12..08a4edf99255 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java @@ -18,19 +18,24 @@ package com.intellij.xdebugger.impl.breakpoints; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.MultiValuesMap; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.ex.http.HttpFileSystem; import com.intellij.openapi.vfs.ex.http.HttpVirtualFileListener; import com.intellij.util.EventDispatcher; +import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; +import com.intellij.util.xmlb.XmlSerializer; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.MapAnnotation; import com.intellij.util.xmlb.annotations.Tag; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.*; import com.intellij.xdebugger.impl.XDebuggerManagerImpl; +import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,7 +46,10 @@ import java.util.*; * @author nik */ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentStateComponent { + private static final Logger LOG = Logger.getInstance("#com.intellij.xdebugger.impl.breakpoints.XBreakpointManagerImpl"); + public static final SkipDefaultValuesSerializationFilters SERIALIZATION_FILTER = new SkipDefaultValuesSerializationFilters(); private final MultiValuesMap> myBreakpoints = new MultiValuesMap>(true); + private final Map> myDefaultBreakpoints = new LinkedHashMap>(); private final Map> myDispatchers = new HashMap>(); private final Map, XBreakpointTypeDialogState> myBreakpointsDialogSettings = new HashMap, XBreakpointTypeDialogState>(); private final EventDispatcher myAllBreakpointsDispatcher; @@ -99,15 +107,29 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta @NotNull public XBreakpoint addBreakpoint(final XBreakpointType,T> type, @Nullable final T properties) { ApplicationManager.getApplication().assertWriteAccessAllowed(); - XBreakpointBase.BreakpointState state = new XBreakpointBase.BreakpointState,T,XBreakpointType,T>>(true, type.getId()); + return addBreakpoint(type, properties, false, true); + } + + private XBreakpointBase addBreakpoint(XBreakpointType, T> type, + T properties, + final boolean defaultBreakpoint, + final boolean initUI) { + XBreakpointBase.BreakpointState state = new XBreakpointBase.BreakpointState,T,XBreakpointType,T>>(!defaultBreakpoint, type.getId()); XBreakpointBase breakpoint = new XBreakpointBase,T, XBreakpointBase.BreakpointState>(type, this, properties, state); - addBreakpoint(breakpoint, true); + addBreakpoint(breakpoint, defaultBreakpoint, initUI); return breakpoint; } - private void addBreakpoint(final XBreakpointBase breakpoint, boolean initUI) { + private void addBreakpoint(final XBreakpointBase breakpoint, final boolean defaultBreakpoint, + boolean initUI) { XBreakpointType type = breakpoint.getType(); - myBreakpoints.put(type, breakpoint); + if (defaultBreakpoint) { + LOG.assertTrue(!myDefaultBreakpoints.containsKey(type), "Cannot have more than one default breakpoint (type " + type.getId() + ")"); + myDefaultBreakpoints.put(type, breakpoint); + } + else { + myBreakpoints.put(type, breakpoint); + } if (breakpoint instanceof XLineBreakpointImpl) { myLineBreakpointManager.registerBreakpoint((XLineBreakpointImpl)breakpoint, initUI); } @@ -138,6 +160,10 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta public void removeBreakpoint(@NotNull final XBreakpoint breakpoint) { ApplicationManager.getApplication().assertWriteAccessAllowed(); + doRemoveBreakpoint(breakpoint); + } + + private void doRemoveBreakpoint(XBreakpoint breakpoint) { XBreakpointType type = breakpoint.getType(); XBreakpointBase breakpointBase = (XBreakpointBase)breakpoint; myBreakpoints.remove(type, breakpointBase); @@ -158,26 +184,32 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta final int line, @Nullable final T properties) { ApplicationManager.getApplication().assertWriteAccessAllowed(); XLineBreakpointImpl breakpoint = new XLineBreakpointImpl(type, this, fileUrl, line, properties); - addBreakpoint(breakpoint, true); + addBreakpoint(breakpoint, false, true); return breakpoint; } @NotNull public XBreakpointBase[] getAllBreakpoints() { ApplicationManager.getApplication().assertReadAccessAllowed(); - Collection> breakpoints = myBreakpoints.values(); + List> breakpoints = new ArrayList>(); + breakpoints.addAll(myDefaultBreakpoints.values()); + breakpoints.addAll(myBreakpoints.values()); return breakpoints.toArray(new XBreakpointBase[breakpoints.size()]); } + @SuppressWarnings({"unchecked"}) @NotNull public > Collection getBreakpoints(@NotNull final XBreakpointType type) { ApplicationManager.getApplication().assertReadAccessAllowed(); Collection> breakpoints = myBreakpoints.get(type); - if (breakpoints == null) { - return Collections.emptyList(); - } - //noinspection unchecked - return Collections.unmodifiableCollection((Collection)breakpoints); + Collection regular = breakpoints != null ? Collections.unmodifiableCollection((Collection)breakpoints) : Collections.emptyList(); + + final XBreakpointBase defaultBreakpoint = myDefaultBreakpoints.get(type); + if (defaultBreakpoint == null) return regular; + List result = new ArrayList(); + result.add((B)defaultBreakpoint); + result.addAll(regular); + return result; } @Nullable @@ -196,6 +228,12 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta return null; } + @Override + public boolean isDefaultBreakpoint(@NotNull XBreakpoint breakpoint) { + //noinspection SuspiciousMethodCalls + return myDefaultBreakpoints.values().contains(breakpoint); + } + private EventDispatcher getOrCreateDispatcher(final XBreakpointType type) { EventDispatcher dispatcher = myDispatchers.get(type); if (dispatcher == null) { @@ -242,6 +280,12 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta public BreakpointManagerState getState() { myDependentBreakpointManager.saveState(); BreakpointManagerState state = new BreakpointManagerState(); + for (XBreakpointBase breakpoint : myDefaultBreakpoints.values()) { + final XBreakpointBase.BreakpointState breakpointState = breakpoint.getState(); + if (differsFromDefault(breakpoint.getType(), breakpointState)) { + state.getDefaultBreakpoints().add(breakpointState); + } + } for (XBreakpointBase breakpoint : myBreakpoints.values()) { state.getBreakpoints().add(breakpoint.getState()); } @@ -251,6 +295,19 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta return state; } + private static

boolean differsFromDefault(XBreakpointType type, + XBreakpointBase.BreakpointState state) { + final P defaultProperties = type.createDefaultBreakpointProperties(); + if (defaultProperties == null) { + return false; + } + XBreakpointBase.BreakpointState defaultState = new XBreakpointBase.BreakpointState(false, type.getId()); + defaultState.setPropertiesElement(XmlSerializer.serialize(defaultProperties)); + Element defaultElement = XmlSerializer.serialize(defaultState, SERIALIZATION_FILTER); + Element currentElement = XmlSerializer.serialize(state, SERIALIZATION_FILTER); + return !JDOMUtil.areElementsEqual(defaultElement, currentElement); + } + public void loadState(final BreakpointManagerState state) { myBreakpointsDialogSettings.clear(); for (Map.Entry entry : state.getBreakpointTypeDialogProperties().entrySet()) { @@ -260,17 +317,41 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta } } - removeAllBreakpoints(); - for (XBreakpointBase.BreakpointState breakpointState : state.getBreakpoints()) { - XBreakpointBase breakpoint = createBreakpoint(breakpointState); - if (breakpoint != null) { - addBreakpoint(breakpoint, false); + myDefaultBreakpoints.clear(); + for (XBreakpointBase.BreakpointState breakpointState : state.getDefaultBreakpoints()) { + loadBreakpoint(breakpointState, true); + } + for (XBreakpointType type : XBreakpointUtil.getBreakpointTypes()) { + if (!myDefaultBreakpoints.containsKey(type)) { + addDefaultBreakpoint(type); } } + + for (XBreakpointBase breakpoint : myBreakpoints.values()) { + doRemoveBreakpoint(breakpoint); + } + for (XBreakpointBase.BreakpointState breakpointState : state.getBreakpoints()) { + loadBreakpoint(breakpointState, false); + } myDependentBreakpointManager.loadState(); myLineBreakpointManager.updateBreakpointsUI(); } + private

void addDefaultBreakpoint(XBreakpointType type) { + final P properties = type.createDefaultBreakpointProperties(); + if (properties != null) { + //noinspection unchecked + addBreakpoint((XBreakpointType, P>)type, properties, true, false); + } + } + + private void loadBreakpoint(XBreakpointBase.BreakpointState breakpointState, final boolean defaultBreakpoint) { + XBreakpointBase breakpoint = createBreakpoint(breakpointState); + if (breakpoint != null) { + addBreakpoint(breakpoint, defaultBreakpoint, false); + } + } + @Nullable public XBreakpointTypeDialogState getDialogState(@NotNull XBreakpointType type) { return myBreakpointsDialogSettings.get(type); @@ -280,27 +361,30 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta myBreakpointsDialogSettings.put(type, dialogState); } - private void removeAllBreakpoints() { - for (XBreakpointBase breakpoint : myBreakpoints.values()) { - removeBreakpoint(breakpoint); - } - } - @Nullable private XBreakpointBase createBreakpoint(final XBreakpointBase.BreakpointState breakpointState) { XBreakpointType type = XBreakpointUtil.findType(breakpointState.getTypeId()); - if (type == null) return null; + if (type == null) return null; + //noinspection unchecked return breakpointState.createBreakpoint(type, this); } @Tag("breakpoint-manager") public static class BreakpointManagerState { + private List myDefaultBreakpoints = new ArrayList(); private List myBreakpoints = new ArrayList(); private Map myBreakpointTypeDialogProperties = new HashMap(); + @Tag("default-breakpoints") + @AbstractCollection(surroundWithTag = false) + public List getDefaultBreakpoints() { + return myDefaultBreakpoints; + } + @Tag("breakpoints") - @AbstractCollection(surroundWithTag = false, elementTypes = {XBreakpointBase.BreakpointState.class, XLineBreakpointImpl.LineBreakpointState.class}) + @AbstractCollection(surroundWithTag = false, + elementTypes = {XBreakpointBase.BreakpointState.class, XLineBreakpointImpl.LineBreakpointState.class}) public List getBreakpoints() { return myBreakpoints; } @@ -316,6 +400,10 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta myBreakpoints = breakpoints; } + public void setDefaultBreakpoints(List defaultBreakpoints) { + myDefaultBreakpoints = defaultBreakpoints; + } + public void setBreakpointTypeDialogProperties(final Map breakpointTypeDialogProperties) { myBreakpointTypeDialogProperties = breakpointTypeDialogProperties; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java index 2ed69ef9f7db..5c47dac8d657 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java @@ -69,7 +69,7 @@ public class XBreakpointsPanel> extends AbstractBreakpo myAllGroupingRules = new ArrayList>(myType.getGroupingRules()); mySelectedGroupingRules = getInitialGroupingRules(); - myTree = XBreakpointsTree.createTree(myType, mySelectedGroupingRules, myParentDialog); + myTree = XBreakpointsTree.createTree(myType, mySelectedGroupingRules, myParentDialog, getBreakpointManager()); myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { public void valueChanged(final TreeSelectionEvent e) { onSelectionChanged(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsTree.java index e3371b4621f3..11f1f701d63b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsTree.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsTree.java @@ -25,6 +25,7 @@ import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.xdebugger.breakpoints.XBreakpoint; +import com.intellij.xdebugger.breakpoints.XBreakpointManager; import com.intellij.xdebugger.breakpoints.XBreakpointType; import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup; import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule; @@ -53,11 +54,13 @@ public class XBreakpointsTree> extends CheckboxTree { private final MultiValuesMap, XBreakpointGroup> myGroups = new MultiValuesMap, XBreakpointGroup>(); private XBreakpointsTree(final XBreakpointType type, final CheckedTreeNode root, - Collection> groupingRules, DialogWrapper parentDialog) { + Collection> groupingRules, + DialogWrapper parentDialog, + XBreakpointManager breakpointManager) { super(new BreakpointsTreeCellRenderer(), root); myRoot = root; myParentDialog = parentDialog; - myComparator = new TreeNodeComparator(type); + myComparator = new TreeNodeComparator(type, breakpointManager); setGroupingRulesInternal(groupingRules); } @@ -68,8 +71,8 @@ public class XBreakpointsTree> extends CheckboxTree { public static > XBreakpointsTree createTree(final XBreakpointType type, final Collection> groupingRules, - DialogWrapper parentDialog) { - return new XBreakpointsTree(type, new CheckedTreeNode("root"), groupingRules, parentDialog); + DialogWrapper parentDialog, XBreakpointManager breakpointManager) { + return new XBreakpointsTree(type, new CheckedTreeNode("root"), groupingRules, parentDialog, breakpointManager); } public void buildTree(@NotNull Collection breakpoints) { @@ -254,15 +257,23 @@ public class XBreakpointsTree> extends CheckboxTree { private static class TreeNodeComparator> implements Comparator { private final Comparator myBreakpointComparator; + private final XBreakpointManager myBreakpointManager; - public TreeNodeComparator(final XBreakpointType type) { + public TreeNodeComparator(final XBreakpointType type, XBreakpointManager breakpointManager) { + myBreakpointManager = breakpointManager; myBreakpointComparator = type.getBreakpointComparator(); } public int compare(final TreeNode o1, final TreeNode o2) { if (o1 instanceof BreakpointNode && o2 instanceof BreakpointNode) { + //noinspection unchecked B b1 = (B)((BreakpointNode)o1).getBreakpoint(); + //noinspection unchecked B b2 = (B)((BreakpointNode)o2).getBreakpoint(); + boolean default1 = myBreakpointManager.isDefaultBreakpoint(b1); + boolean default2 = myBreakpointManager.isDefaultBreakpoint(b2); + if (default1 && !default2) return -1; + if (!default1 && default2) return 1; return myBreakpointComparator.compare(b1, b2); } if (o1 instanceof BreakpointsGroupNode && o2 instanceof BreakpointsGroupNode) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/actions/RemoveBreakpointAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/actions/RemoveBreakpointAction.java index 13661e228a47..f7cf0f960170 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/actions/RemoveBreakpointAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/actions/RemoveBreakpointAction.java @@ -38,7 +38,12 @@ public class RemoveBreakpointAction> extends XBreakpoin } public boolean isEnabled(@NotNull final Collection breakpoints) { - return !breakpoints.isEmpty(); + for (B breakpoint : breakpoints) { + if (!myBreakpointsPanel.getBreakpointManager().isDefaultBreakpoint(breakpoint)) { + return true; + } + } + return false; } public void perform(@NotNull final Collection breakpoints) { @@ -46,7 +51,9 @@ public class RemoveBreakpointAction> extends XBreakpoin new WriteAction() { protected void run(final Result result) { for (B breakpoint : breakpoints) { - breakpointManager.removeBreakpoint(breakpoint); + if (!breakpointManager.isDefaultBreakpoint(breakpoint)) { + breakpointManager.removeBreakpoint(breakpoint); + } } } }.execute(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java index 936e382979aa..18c9e78c8583 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java @@ -63,7 +63,7 @@ public class XDebuggerEvaluationDialog extends DialogWrapper { setOKButtonText(XDebuggerBundle.message("xdebugger.button.evaluate")); setCancelButtonText(XDebuggerBundle.message("xdebugger.evaluate.dialog.close")); - myTreePanel = new XDebuggerTreePanel(session, editorsProvider, sourcePosition, XDebuggerActions.EVALUATE_DIALOG_TREE_POPUP_GROUP); + myTreePanel = new XDebuggerTreePanel(session, editorsProvider, myDisposable, sourcePosition, XDebuggerActions.EVALUATE_DIALOG_TREE_POPUP_GROUP); myResultPanel = new JPanel(new BorderLayout()); myResultPanel.add(new JLabel(XDebuggerBundle.message("xdebugger.evaluate.label.result")), BorderLayout.NORTH); myResultPanel.add(myTreePanel.getMainPanel(), BorderLayout.CENTER); @@ -149,11 +149,6 @@ public class XDebuggerEvaluationDialog extends DialogWrapper { myInputComponent.getInputEditor().selectAll(); } - protected void dispose() { - myTreePanel.dispose(); - super.dispose(); - } - protected String getDimensionServiceKey() { return "#xdebugger.evaluate"; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java index 80972d7ee42d..385a15d9eae8 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java @@ -33,6 +33,7 @@ import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; import com.intellij.xdebugger.frame.XFullValueEvaluator; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.frame.XValueNode; +import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint; import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; @@ -142,7 +143,7 @@ public class XValueHint extends AbstractValueHint { private void showTree(final XValue value, final String name) { XDebuggerTree tree = new XDebuggerTree(myDebugSession, myDebugSession.getDebugProcess().getEditorsProvider(), - myDebugSession.getCurrentPosition()); + myDebugSession.getCurrentPosition(), XDebuggerActions.VALUE_HINT_TREE_POPUP_GROUP); tree.getModel().addTreeModelListener(createTreeListener(tree)); XValueHintTreeComponent component = new XValueHintTreeComponent(this, tree, Pair.create(value, name)); showTreePopup(component, tree, name); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewBase.java index 4496f0e7969b..4feaa5ef5c99 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewBase.java @@ -15,10 +15,11 @@ */ package com.intellij.xdebugger.impl.frame; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebugSessionAdapter; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; -import com.intellij.openapi.Disposable; /** * @author nik @@ -32,6 +33,7 @@ public abstract class XDebugViewBase implements Disposable { mySession = session; mySessionListener = new MyDebugSessionListener(); mySession.addSessionListener(mySessionListener); + Disposer.register(parentDisposable, this); } public void rebuildView() { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java index 5a0a3d2aabf9..f61a23debdb2 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java @@ -43,7 +43,7 @@ public class XVariablesView extends XDebugViewBase { public XVariablesView(@NotNull XDebugSession session, final Disposable parentDisposable) { super(session, parentDisposable); XDebuggerEditorsProvider editorsProvider = session.getDebugProcess().getEditorsProvider(); - myDebuggerTreePanel = new XDebuggerTreePanel(session, editorsProvider, null, XDebuggerActions.VARIABLES_TREE_POPUP_GROUP); + myDebuggerTreePanel = new XDebuggerTreePanel(session, editorsProvider, this, null, XDebuggerActions.VARIABLES_TREE_POPUP_GROUP); DnDManager.getInstance().registerSource(myDebuggerTreePanel, myDebuggerTreePanel.getTree()); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesView.java index 09f28dee1895..1154245d9576 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesView.java @@ -56,7 +56,7 @@ public class XWatchesView extends XDebugViewBase implements DnDNativeTarget { public XWatchesView(final XDebugSession session, final Disposable parentDisposable, final XDebugSessionData sessionData) { super(session, parentDisposable); - myTreePanel = new XDebuggerTreePanel(session, session.getDebugProcess().getEditorsProvider(), null, + myTreePanel = new XDebuggerTreePanel(session, session.getDebugProcess().getEditorsProvider(), this, null, XDebuggerActions.WATCHES_TREE_POPUP_GROUP); ActionManager actionManager = ActionManager.getInstance(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java index 425aec3cb0a2..b8265e872ab6 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java @@ -16,12 +16,11 @@ package com.intellij.xdebugger.impl.ui.tree; import com.intellij.ide.dnd.aware.DnDAwareTree; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.DataKey; -import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.changes.issueLinks.TreeLinkMouseListener; +import com.intellij.ui.PopupHandler; import com.intellij.ui.TreeSpeedSearch; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; @@ -29,14 +28,18 @@ import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; +import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.ui.tree.nodes.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; +import java.awt.*; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.List; @@ -44,7 +47,7 @@ import java.util.List; /** * @author nik */ -public class XDebuggerTree extends DnDAwareTree implements DataProvider { +public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposable { private static final DataKey XDEBUGGER_TREE_KEY = DataKey.create("xdebugger.tree"); private static final Convertor SPEED_SEARCH_CONVERTER = new Convertor() { public String convert(TreePath o) { @@ -67,8 +70,12 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider { private XSourcePosition mySourcePosition; private final List myListeners = ContainerUtil.createEmptyCOWList(); private final XDebugSession mySession; + private final PopupHandler myPopupHandler; - public XDebuggerTree(final @NotNull XDebugSession session, final @NotNull XDebuggerEditorsProvider editorsProvider, final @Nullable XSourcePosition sourcePosition) { + public XDebuggerTree(final @NotNull XDebugSession session, + final @NotNull XDebuggerEditorsProvider editorsProvider, + final @Nullable XSourcePosition sourcePosition, + final @NotNull String popupActionGroupId) { mySession = session; myProject = session.getProject(); myEditorsProvider = editorsProvider; @@ -104,6 +111,17 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider { } }); new TreeSpeedSearch(this, SPEED_SEARCH_CONVERTER); + + final ActionManager actionManager = ActionManager.getInstance(); + myPopupHandler = new PopupHandler() { + public void invokePopup(final Component comp, final int x, final int y) { + final ActionGroup group = (ActionGroup)actionManager.getAction(popupActionGroupId); + ActionPopupMenu popupMenu = actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, group); + popupMenu.getComponent().show(comp, x, y); + } + }; + addMouseListener(myPopupHandler); + registerShortcuts(); } public void addTreeListener(@NotNull XDebuggerTreeListener listener) { @@ -187,6 +205,20 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider { } } + public void dispose() { + ActionManager actionManager = ActionManager.getInstance(); + actionManager.getAction(XDebuggerActions.SET_VALUE).unregisterCustomShortcutSet(this); + actionManager.getAction(XDebuggerActions.COPY_VALUE).unregisterCustomShortcutSet(this); + actionManager.getAction(XDebuggerActions.JUMP_TO_SOURCE).unregisterCustomShortcutSet(this); + } + + private void registerShortcuts() { + ActionManager actionManager = ActionManager.getInstance(); + actionManager.getAction(XDebuggerActions.SET_VALUE).registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)), this); + actionManager.getAction(XDebuggerActions.COPY_VALUE).registerCustomShortcutSet(CommonShortcuts.getCopy(), this); + actionManager.getAction(XDebuggerActions.JUMP_TO_SOURCE).registerCustomShortcutSet(CommonShortcuts.getEditSource(), this); + } + private static void markNodesObsolete(final XValueContainerNode node) { node.setObsolete(); List> loadedChildren = node.getLoadedChildren(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreePanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreePanel.java index e3318e620a1a..6e2dcbd50fd1 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreePanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreePanel.java @@ -19,16 +19,15 @@ import com.intellij.ide.dnd.DnDAction; import com.intellij.ide.dnd.DnDDragStartBean; import com.intellij.ide.dnd.DnDSource; import com.intellij.ide.dnd.aware.DnDAwareTree; -import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; -import com.intellij.ui.PopupHandler; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.treeStructure.Tree; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; -import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -36,7 +35,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.KeyEvent; /** * @author nik @@ -44,33 +42,14 @@ import java.awt.event.KeyEvent; public class XDebuggerTreePanel implements DnDSource { private final XDebuggerTree myTree; private final JPanel myMainPanel; - private final PopupHandler myPopupHandler; - public XDebuggerTreePanel(final @NotNull XDebugSession session, final @NotNull XDebuggerEditorsProvider editorsProvider, final @Nullable XSourcePosition sourcePosition, + public XDebuggerTreePanel(final @NotNull XDebugSession session, final @NotNull XDebuggerEditorsProvider editorsProvider, + @NotNull Disposable parentDisposable, final @Nullable XSourcePosition sourcePosition, @NotNull @NonNls final String popupActionGroupId) { - myTree = new XDebuggerTree(session, editorsProvider, sourcePosition); + myTree = new XDebuggerTree(session, editorsProvider, sourcePosition, popupActionGroupId); myMainPanel = new JPanel(new BorderLayout()); myMainPanel.add(ScrollPaneFactory.createScrollPane(myTree), BorderLayout.CENTER); - final ActionManager actionManager = ActionManager.getInstance(); - myPopupHandler = new PopupHandler() { - public void invokePopup(final Component comp, final int x, final int y) { - final ActionGroup group = (ActionGroup)actionManager.getAction(popupActionGroupId); - ActionPopupMenu popupMenu = actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, group); - popupMenu.getComponent().show(comp, x, y); - } - }; - actionManager.getAction(XDebuggerActions.SET_VALUE).registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)), myTree); - actionManager.getAction(XDebuggerActions.COPY_VALUE).registerCustomShortcutSet(CommonShortcuts.getCopy(), myTree); - actionManager.getAction(XDebuggerActions.JUMP_TO_SOURCE).registerCustomShortcutSet(CommonShortcuts.getEditSource(), myTree); - - myTree.addMouseListener(myPopupHandler); - } - - public void dispose() { - ActionManager actionManager = ActionManager.getInstance(); - actionManager.getAction(XDebuggerActions.SET_VALUE).unregisterCustomShortcutSet(myTree); - actionManager.getAction(XDebuggerActions.JUMP_TO_SOURCE).unregisterCustomShortcutSet(myTree); - myTree.removeMouseListener(myPopupHandler); + Disposer.register(parentDisposable, myTree); } public XDebuggerTree getTree() { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java index 7425fc31640b..b738589e33e9 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java @@ -38,7 +38,7 @@ public class XInspectDialog extends DialogWrapper { super(session.getProject(), false); setTitle(XDebuggerBundle.message("inspect.value.dialog.title", nodeName)); setModal(false); - myTreePanel = new XDebuggerTreePanel(session, editorsProvider, sourcePosition, XDebuggerActions.INSPECT_TREE_POPUP_GROUP); + myTreePanel = new XDebuggerTreePanel(session, editorsProvider, myDisposable, sourcePosition, XDebuggerActions.INSPECT_TREE_POPUP_GROUP); XDebuggerTree tree = myTreePanel.getTree(); tree.setRoot(new XValueNodeImpl(tree, null, value), true); init(); @@ -58,9 +58,4 @@ public class XInspectDialog extends DialogWrapper { protected String getDimensionServiceKey() { return "#xdebugger.XInspectDialog"; } - - protected void dispose() { - myTreePanel.dispose(); - super.dispose(); - } } diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java index 21115b46efc6..a6e23eb0fee2 100644 --- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java @@ -35,12 +35,12 @@ public class XBreakpointManagerTest extends XBreakpointsTestCase { assertSameElements(myBreakpointManager.getAllBreakpoints(), breakpoint, lineBreakpoint); assertSame(lineBreakpoint, assertOneElement(myBreakpointManager.getBreakpoints(MY_LINE_BREAKPOINT_TYPE))); - assertSame(breakpoint, assertOneElement(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE))); + assertSame(breakpoint, getSingleBreakpoint()); myBreakpointManager.removeBreakpoint(lineBreakpoint); assertSame(breakpoint, assertOneElement(myBreakpointManager.getAllBreakpoints())); assertTrue(myBreakpointManager.getBreakpoints(MY_LINE_BREAKPOINT_TYPE).isEmpty()); - assertSame(breakpoint, assertOneElement(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE))); + assertSame(breakpoint, getSingleBreakpoint()); myBreakpointManager.removeBreakpoint(breakpoint); assertEquals(0, myBreakpointManager.getAllBreakpoints().length); @@ -56,13 +56,14 @@ public class XBreakpointManagerTest extends XBreakpointsTestCase { breakpoint.setLogMessage(true); myBreakpointManager.addBreakpoint(MY_SIMPLE_BREAKPOINT_TYPE, new MyBreakpointProperties("123")); - Element element = save(); - //System.out.println(JDOMUtil.writeElement(element, SystemProperties.getLineSeparator())); - load(element); + reload(); XBreakpoint[] breakpoints = myBreakpointManager.getAllBreakpoints(); - assertEquals(2, breakpoints.length); + assertEquals(3, breakpoints.length); - XLineBreakpoint lineBreakpoint = assertInstanceOf(breakpoints[0], XLineBreakpoint.class); + assertTrue(myBreakpointManager.isDefaultBreakpoint(breakpoints[0])); + assertEquals("default", assertInstanceOf(breakpoints[0].getProperties(), MyBreakpointProperties.class).myOption); + + XLineBreakpoint lineBreakpoint = assertInstanceOf(breakpoints[1], XLineBreakpoint.class); assertEquals(239, lineBreakpoint.getLine()); assertEquals("myurl", lineBreakpoint.getFileUrl()); assertEquals("abc", assertInstanceOf(lineBreakpoint.getProperties(), MyBreakpointProperties.class).myOption); @@ -71,9 +72,36 @@ public class XBreakpointManagerTest extends XBreakpointsTestCase { assertTrue(lineBreakpoint.isLogMessage()); assertEquals(SuspendPolicy.NONE, lineBreakpoint.getSuspendPolicy()); - assertEquals("123", assertInstanceOf(breakpoints[1].getProperties(), MyBreakpointProperties.class).myOption); - assertEquals(SuspendPolicy.ALL, breakpoints[1].getSuspendPolicy()); - assertFalse(breakpoints[1].isLogMessage()); + assertEquals("123", assertInstanceOf(breakpoints[2].getProperties(), MyBreakpointProperties.class).myOption); + assertEquals(SuspendPolicy.ALL, breakpoints[2].getSuspendPolicy()); + assertFalse(breakpoints[2].isLogMessage()); + } + + public void testDoNotSaveUnmodifiedDefaultBreakpoint() throws Exception { + reload(); + + assertEquals("default", getSingleBreakpoint().getProperties().myOption); + Element element = save(); + assertEquals(0, element.getContent().size()); + } + + public void testSaveEnabledDefaultBreakpoint() throws Exception { + reload(); + final XBreakpoint breakpoint = getSingleBreakpoint(); + breakpoint.setEnabled(true); + + assertFalse(save().getContent().isEmpty()); + reload(); + assertTrue(getSingleBreakpoint().isEnabled()); + } + + public void testSaveDefaultBreakpointWithModifiedProperties() throws Exception { + reload(); + getSingleBreakpoint().getProperties().myOption = "changed"; + + assertFalse(save().getContent().isEmpty()); + reload(); + assertEquals("changed", getSingleBreakpoint().getProperties().myOption); } public void testListener() throws Exception { @@ -106,4 +134,13 @@ public class XBreakpointManagerTest extends XBreakpointsTestCase { myBreakpointManager.addLineBreakpoint(MY_LINE_BREAKPOINT_TYPE, "url", 239, new MyBreakpointProperties("a")); assertEquals("", out.toString()); } + + private XBreakpoint getSingleBreakpoint() { + return assertOneElement(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE)); + } + + private void reload() { + Element element = save(); + load(element); + } } diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestCase.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestCase.java index 1918086be9c5..d6b37c35569c 100644 --- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestCase.java +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestCase.java @@ -88,6 +88,11 @@ public abstract class XDebuggerTestCase extends PlatformLiteFixture { public MyBreakpointProperties createProperties() { return new MyBreakpointProperties(); } + + @Override + public MyBreakpointProperties createDefaultBreakpointProperties() { + return new MyBreakpointProperties("default"); + } } protected static class MyBreakpointProperties extends XBreakpointProperties { diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java index f9d4ef55250b..11b213d5bfa1 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java @@ -61,7 +61,7 @@ public class GithubUtil { public static List getAvailableRepos(final String login, final String password) { try { - final HttpMethod method = doREST(login, password, "/repos/show/" + login, false); + final HttpMethod method = doREST(login, password, "/repos/watched/" + login, false); final InputStream stream = method.getResponseBodyAsStream(); final Element element = new SAXBuilder(false).build(stream).getRootElement(); final List repositories = element.getChildren(); diff --git a/resources-en/src/tips/tips.xml b/resources-en/src/tips/tips.xml index 6d3a222eba79..5bfef722c932 100644 --- a/resources-en/src/tips/tips.xml +++ b/resources-en/src/tips/tips.xml @@ -3,75 +3,105 @@ --> - - + + + + - - - + + + + + + - - - - + + + + + + + - - + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - + + + + - + + - + + - + + - + + - - + + + + - + + - + + - + + - + + @@ -82,21 +112,22 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/resources/src/ProductivityFeaturesRegistry.xml b/resources/src/ProductivityFeaturesRegistry.xml index b55bdfdf9c66..cacef83771c2 100644 --- a/resources/src/ProductivityFeaturesRegistry.xml +++ b/resources/src/ProductivityFeaturesRegistry.xml @@ -78,6 +78,12 @@ min-usage-count="3" first-show="5" successive-show="5"/> + @@ -454,4 +460,4 @@ successive-show="10" min-usage-count="1"/> - \ No newline at end of file + diff --git a/resources/src/idea/IdeaActions.xml b/resources/src/idea/IdeaActions.xml index 5617e7f3af70..192d502c1211 100644 --- a/resources/src/idea/IdeaActions.xml +++ b/resources/src/idea/IdeaActions.xml @@ -125,6 +125,7 @@ +