diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java index 298e1c663a34..197364969340 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java @@ -19,16 +19,29 @@ import com.intellij.extapi.psi.PsiFileBase; import com.intellij.lang.Language; import com.intellij.openapi.fileTypes.FileType; import com.intellij.psi.FileViewProvider; +import com.intellij.psi.util.PsiTreeUtil; +import org.intellij.lang.regexp.psi.RegExpGroup; import org.jetbrains.annotations.NotNull; +import java.util.Collection; + + public class RegExpFile extends PsiFileBase { - public RegExpFile(FileViewProvider viewProvider, final Language language) { - super(viewProvider, language); - } + public RegExpFile(FileViewProvider viewProvider, final Language language) { + super(viewProvider, language); + } - @NotNull - public FileType getFileType() { - return RegExpFileType.INSTANCE; - } + @NotNull + public FileType getFileType() { + return RegExpFileType.INSTANCE; + } + + /** + * @return Regexp groups this file has + */ + @NotNull + public Collection getGroups() { + return PsiTreeUtil.findChildrenOfType(this, RegExpGroup.class); + } } diff --git a/build/conf/nsis/idea.nsi b/build/conf/nsis/idea.nsi index 73418e56f1e5..e9f4b49f101c 100644 --- a/build/conf/nsis/idea.nsi +++ b/build/conf/nsis/idea.nsi @@ -562,6 +562,7 @@ ${If} $8 > $control_fields StrCpy $2 "" !insertmacro MUI_HEADER_TEXT "$(uninstall_previous_installations_title)" "$(uninstall_previous_installations)" !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field 1" "Text" "$(uninstall_previous_installations_prompt)" + !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field 3" "Flags" "FOCUS" !insertmacro INSTALLOPTIONS_DISPLAY "UninstallOldVersions.ini" ;uninstall chosen installation(s) diff --git a/build/scripts/common_tests.gant b/build/scripts/common_tests.gant index e7aaf1a5d34e..d9e41382c75d 100644 --- a/build/scripts/common_tests.gant +++ b/build/scripts/common_tests.gant @@ -51,6 +51,7 @@ target('run_tests': 'Run java tests') { pass("idea.test.group") pass("idea.test.patterns") pass("idea.fast.only") + pass("idea.coverage.enabled.build") pass("teamcity.build.tempDir") pass("teamcity.tests.recentlyFailedTests.file") jvmarg(value: "-Didea.platform.prefix=Idea") diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java index 7b76b9738843..02f4ee44fd53 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java @@ -110,7 +110,9 @@ public class JavaEditorTextProviderImpl implements EditorTextProvider { else if (parent instanceof PsiInstanceOfExpression || parent instanceof PsiBinaryExpression || parent instanceof PsiPolyadicExpression - || parent instanceof PsiPrefixExpression) { + || parent instanceof PsiPrefixExpression + || parent instanceof PsiConditionalExpression + ) { if (allowMethodCalls || !DebuggerUtils.hasSideEffects(parent)) { expression = parent; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java index f06574569db8..98c772d75044 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java @@ -63,6 +63,6 @@ public class XBreakpointGroupingByPackageRule extends XBreakpointGroupingRule @Nullable @Override public Icon getIcon() { - return AllIcons.Nodes.Package; + return AllIcons.Actions.GroupByPackage; } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java index ebbef2c2ec44..414960b1980a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java @@ -51,7 +51,7 @@ public class AnyExceptionBreakpoint extends ExceptionBreakpoint { public void createRequest(DebugProcessImpl debugProcess) { DebuggerManagerThreadImpl.assertIsManagerThread(); - if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) { + if (!shouldCreateRequest(debugProcess)) { return; } super.processClassPrepare(debugProcess, null); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java index 6879407b3c9a..6b1c52c1085a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java @@ -46,6 +46,7 @@ import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.breakpoints.SuspendPolicy; import com.intellij.xdebugger.breakpoints.XBreakpoint; import com.intellij.xdebugger.breakpoints.XLineBreakpoint; +import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.XDebuggerHistoryManager; import com.intellij.xdebugger.impl.XDebuggerUtilImpl; import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase; @@ -95,7 +96,15 @@ public abstract class Breakpoint

implements * Request for creating all needed JPDA requests in the specified VM * @param debuggerProcess the requesting process */ - public abstract void createRequest(DebugProcessImpl debuggerProcess); + public abstract void createRequest(DebugProcessImpl debugProcess); + + protected boolean shouldCreateRequest(DebugProcessImpl debugProcess) { + JavaDebugProcess process = debugProcess.getXdebugProcess(); + return process != null + && debugProcess.isAttached() + && ((XDebugSessionImpl)process.getSession()).isBreakpointActive(myXBreakpoint) + && debugProcess.getRequestsManager().findRequests(this).isEmpty(); + } /** * Request for creating all needed JPDA requests in the specified VM diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java index d6cbf1487ab9..cc373743736d 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java @@ -17,10 +17,7 @@ package com.intellij.debugger.ui.breakpoints; import com.intellij.CommonBundle; import com.intellij.debugger.*; -import com.intellij.debugger.engine.DebugProcess; -import com.intellij.debugger.engine.DebugProcessImpl; -import com.intellij.debugger.engine.DebuggerManagerThreadImpl; -import com.intellij.debugger.engine.JVMNameUtil; +import com.intellij.debugger.engine.*; import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.engine.requests.RequestManagerImpl; import com.intellij.debugger.impl.DebuggerContextImpl; @@ -300,10 +297,7 @@ public abstract class BreakpointWithHighlighter

createActions(final boolean fromPopup) { final ArrayList result = super.createActions(fromPopup); - result.add(Separator.getInstance()); - result.add(new MyGroupAction()); - if (fromPopup || !(SystemInfo.isMac && Registry.is("ide.new.project.settings"))) { + if (fromPopup || !Registry.is("ide.new.project.settings")) { + result.add(Separator.getInstance()); + result.add(new MyGroupAction()); addCollapseExpandActions(result); } return result; diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java index f7dc89ce5b80..307d608ddbd8 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java @@ -16,7 +16,6 @@ package com.intellij.psi.impl.source.resolve.reference.impl.providers; import com.intellij.psi.*; -import com.intellij.psi.jsp.JspImplicitVariable; import com.intellij.psi.jsp.JspSpiUtil; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.xml.XmlAttribute; @@ -62,8 +61,8 @@ public class MethodPropertyReference extends BasicAttributeValueReference { } } else if (psiElement instanceof PsiClass) { return (PsiClass)psiElement; - } else if (psiElement instanceof JspImplicitVariable) { - final PsiType type=((JspImplicitVariable)psiElement).getType(); + } else if (psiElement instanceof PsiVariable) { + final PsiType type=((PsiVariable)psiElement).getType(); if (type instanceof PsiClassType) { return ((PsiClassType)type).resolve(); } diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java index 92caad03d8ef..33f43ef93fa7 100644 --- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java @@ -579,7 +579,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { FindModel findModel = FindManagerTestUtils.configureFindModel("done"); String text = "/** done done done */"; - findModel.setInCommentsOnly(true); + findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS); FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text); findModel.setRegularExpressions(true); @@ -592,7 +592,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { String prefix = "/*"; String text = prefix + "done*/"; - findModel.setInCommentsOnly(true); + findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS); LightVirtualFile file = new LightVirtualFile("A.java", text); FindResult findResult = myFindManager.findString(text, prefix.length(), findModel, file); @@ -615,8 +615,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { FindModel findModel = FindManagerTestUtils.configureFindModel("^done$"); findModel.setRegularExpressions(true); - findModel.setInStringLiteralsOnly(true); - findModel.setInCommentsOnly(false); + findModel.setSearchContext(FindModel.SearchContext.IN_STRINGS); String text = "\"done\"; 'done'; 'done' \"done2\""; FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text, "java"); @@ -633,7 +632,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { String text = "/** do ne do ne do ne */"; - findModel.setInCommentsOnly(true); + findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS); FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text, "java"); } diff --git a/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java b/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java index 6eda197118bd..6100c98323bc 100644 --- a/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java +++ b/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java @@ -21,9 +21,6 @@ import com.intellij.psi.JavaElementVisitor; * @author yole */ public abstract class JavaJspElementVisitor extends JavaElementVisitor { - public void visitJspImplicitVariable(JspImplicitVariable variable){ - visitImplicitVariable(variable); - } public void visitJspFile(JspFile jspFile) { visitFile(jspFile); diff --git a/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java b/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java index 087180bbc9a3..ea08e96427c0 100644 --- a/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java +++ b/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java @@ -24,12 +24,10 @@ public class FindManagerTestUtils { } public static void runFindInCommentsAndLiterals(FindManager findManager, FindModel findModel, String text, String ext) { - findModel.setInStringLiteralsOnly(true); - findModel.setInCommentsOnly(false); + findModel.setSearchContext(FindModel.SearchContext.IN_STRINGS); runFindForwardAndBackward(findManager, findModel, text, ext); - findModel.setInStringLiteralsOnly(false); - findModel.setInCommentsOnly(true); + findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS); runFindForwardAndBackward(findManager, findModel, text, ext); } diff --git a/platform/core-api/src/com/intellij/ide/caches/FileContent.java b/platform/core-api/src/com/intellij/ide/caches/FileContent.java index 0933b7f19005..c4c6d61c4513 100644 --- a/platform/core-api/src/com/intellij/ide/caches/FileContent.java +++ b/platform/core-api/src/com/intellij/ide/caches/FileContent.java @@ -47,7 +47,7 @@ public class FileContent extends UserDataHolderBase { @NotNull public byte[] getBytes() throws IOException { if (myCachedBytes == null) { - myCachedBytes = myVirtualFile.contentsToByteArray(false); + myCachedBytes = myVirtualFile.isValid() ? myVirtualFile.contentsToByteArray(false) : ArrayUtil.EMPTY_BYTE_ARRAY; } return myCachedBytes; diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java index cd0f15f3796c..9e8c37880589 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java @@ -84,6 +84,20 @@ public class VfsUtilCore { return false; } + /** + * @return {@code true} if {@code url} is located under one of {@code rootUrls} or equal to one of them + */ + public static boolean isUnder(@NotNull String url, @Nullable Collection rootUrls) { + if (rootUrls == null || rootUrls.isEmpty()) return false; + + for (String excludesUrl : rootUrls) { + if (isEqualOrAncestor(excludesUrl, url)) { + return true; + } + } + return false; + } + public static boolean isEqualOrAncestor(@NotNull String ancestorUrl, @NotNull String fileUrl) { if (ancestorUrl.equals(fileUrl)) return true; if (StringUtil.endsWithChar(ancestorUrl, '/')) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java index 7e7483869728..3e1c95ad3766 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java @@ -33,8 +33,13 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; import com.intellij.openapi.externalSystem.util.Order; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.*; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.openapi.roots.SourceFolder; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -151,7 +156,7 @@ public class ContentRootDataService implements ProjectDataService result = ContainerUtil.newArrayList(); - final List currentRules = ContainerUtil.newArrayList(); + final List buffer = ContainerUtil.newArrayList(); String currentSectionStart = null; for (int i = 0; i < getModel().getSize(); i++) { Object element = getModel().getElementAt(i); @@ -174,15 +174,12 @@ public class ArrangementMatchingRulesControl extends JBTable { mySectionRuleManager == null ? null : mySectionRuleManager.getSectionRuleData((StdArrangementMatchRule)element); if (sectionRule != null) { if (sectionRule.isSectionStart()) { - if (currentSectionStart != null) { - result.add(ArrangementSectionRule.create(currentSectionStart, null, currentRules)); - currentRules.clear(); - } + appendBufferedSectionRules(result, buffer, currentSectionStart); currentSectionStart = sectionRule.getText(); } else { - result.add(ArrangementSectionRule.create(StringUtil.notNullize(currentSectionStart), sectionRule.getText(), currentRules)); - currentRules.clear(); + result.add(ArrangementSectionRule.create(StringUtil.notNullize(currentSectionStart), sectionRule.getText(), buffer)); + buffer.clear(); currentSectionStart = null; } } @@ -190,17 +187,34 @@ public class ArrangementMatchingRulesControl extends JBTable { result.add(ArrangementSectionRule.create((StdArrangementMatchRule)element)); } else { - currentRules.add((StdArrangementMatchRule)element); + buffer.add((StdArrangementMatchRule)element); } } } - if (currentSectionStart != null) { - result.add(ArrangementSectionRule.create(currentSectionStart, null, currentRules)); - } + appendBufferedSectionRules(result, buffer, currentSectionStart); return result; } + private static void appendBufferedSectionRules(@NotNull List result, + @NotNull List buffer, + @Nullable String currentSectionStart) { + if (currentSectionStart == null) { + return; + } + + if (buffer.isEmpty()) { + result.add(ArrangementSectionRule.create(currentSectionStart, null)); + } + else { + result.add(ArrangementSectionRule.create(currentSectionStart, null, buffer.get(0))); + for (int j = 1; j < buffer.size(); j++) { + result.add(ArrangementSectionRule.create(buffer.get(j))); + } + buffer.clear(); + } + } + @Override protected void processMouseEvent(MouseEvent e) { int id = e.getID(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java index fe4fc716a5fb..501ea66fd767 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java @@ -17,17 +17,24 @@ package com.intellij.codeInsight.editorActions; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeStyle.CodeStyleFacade; +import com.intellij.formatting.*; +import com.intellij.lang.LanguageFormatting; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Couple; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; @@ -57,27 +64,32 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate { return false; } + Project project = file.getProject(); Document document = editor.getDocument(); + CaretModel caretModel = editor.getCaretModel(); + boolean isUncommitted = PsiDocumentManager.getInstance(project).isUncommited(document); - int caretOffset = editor.getCaretModel().getOffset(); + int caretOffset = caretModel.getOffset(); int offset = CharArrayUtil.shiftForward(document.getCharsSequence(), caretOffset, " \t"); + int offsetInPsi = offset + (isUncommitted ? 1 : 0); int beforeWhitespaceOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), offset - 1, " \t") + 1; - LogicalPosition logicalPosition = caretOffset < offset ? editor.offsetToLogicalPosition(offset) : editor.getCaretModel().getLogicalPosition(); + LogicalPosition logicalPosition = caretOffset < offset ? editor.offsetToLogicalPosition(offset) : caretModel.getLogicalPosition(); int lineStartOffset = document.getLineStartOffset(logicalPosition.line); if (lineStartOffset < beforeWhitespaceOffset) { - if (caretWasAtLineStart && beforeWhitespaceOffset < offset) { - document.deleteString(beforeWhitespaceOffset, offset); - return true; + if (caretWasAtLineStart && beforeWhitespaceOffset <= offset) { + String spacing = getSpacing(file, offsetInPsi); + if (beforeWhitespaceOffset < offset || !spacing.isEmpty()) { + document.replaceString(beforeWhitespaceOffset, offset, spacing); + caretModel.moveToOffset(beforeWhitespaceOffset + spacing.length()); + return true; + } } return false; } - Project project = file.getProject(); CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(project); - PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); // We should calculate indent at line containing the text after caret, cause that text might affect the result (e.g. closing brace in Java) - String indent = codeStyleFacade.getLineIndent(document, caretWasAtLineStart && psiDocumentManager.isUncommited(document) - ? initialCaretOffset : lineStartOffset); + String indent = codeStyleFacade.getLineIndent(document, caretWasAtLineStart && isUncommitted ? initialCaretOffset : lineStartOffset); if (indent == null) { return false; } @@ -87,7 +99,7 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate { if (logicalPosition.column == targetColumn) { if (caretOffset < offset) { - editor.getCaretModel().moveToLogicalPosition(logicalPosition); + caretModel.moveToLogicalPosition(logicalPosition); return true; } return false; @@ -95,7 +107,7 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate { if (caretWasAtLineStart || logicalPosition.column > targetColumn) { document.replaceString(lineStartOffset, offset, indent); - editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logicalPosition.line, targetColumn)); + caretModel.moveToLogicalPosition(new LogicalPosition(logicalPosition.line, targetColumn)); return true; } @@ -108,12 +120,13 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate { int targetOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), prevLineEndOffset - 1, " \t") + 1; if (prevLineStartOffset < targetOffset) { - document.deleteString(targetOffset, offset); - editor.getCaretModel().moveToOffset(targetOffset); + String spacing = getSpacing(file, offsetInPsi); + document.replaceString(targetOffset, offset, spacing); + caretModel.moveToOffset(targetOffset + spacing.length()); } else { document.replaceString(prevLineStartOffset, offset, indent); - editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logicalPosition.line - 1, targetColumn)); + caretModel.moveToLogicalPosition(new LogicalPosition(logicalPosition.line - 1, targetColumn)); } return true; } @@ -140,4 +153,15 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate { } return width; } + + private static String getSpacing(PsiFile file, int offset) { + FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file); + if (builder == null) { + return ""; + } + CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(file.getProject()); + FormattingModel model = builder.createModel(file, settings); + int spacing = FormatterEx.getInstance().getSpacingForBlockAtOffset(model, offset); + return StringUtil.repeatSymbol(' ', spacing); + } } diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 9cb57be6ad9d..1a9afd1e25e5 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -670,12 +670,14 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { } } + @NotNull public Editor getCurrentEditor() { - return ObjectUtils.chooseNotNull(myCurrentEditor, myConsoleEditor); + return ObjectUtils.notNull(myCurrentEditor, myConsoleEditor); } + @NotNull public Language getLanguage() { - return myVirtualFile.getLanguage(); + return ObjectUtils.assertNotNull(myVirtualFile.getLanguage()); } public void setLanguage(@NotNull Language language) { diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index 8a36638d993c..9613ac0dd33f 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -392,6 +392,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data if (secondaryActionsAvailable()) { actionGroup.addAction(new ToggleInCommentsAction(this)).setAsSecondary(true); actionGroup.addAction(new ToggleInLiteralsOnlyAction(this)).setAsSecondary(true); + actionGroup.addAction(new ToggleExceptCommentsAction(this)).setAsSecondary(true); + actionGroup.addAction(new ToggleExceptLiteralsAction(this)).setAsSecondary(true); + actionGroup.addAction(new ToggleExceptCommentsAndLiteralsAction(this)).setAsSecondary(true); } actionGroup.addAction(new TogglePreserveCaseAction(this)); actionGroup.addAction(new ToggleSelectionOnlyAction(this)); @@ -473,8 +476,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data to.setCaseSensitive(from.isCaseSensitive()); to.setWholeWordsOnly(from.isWholeWordsOnly()); to.setRegularExpressions(from.isRegularExpressions()); - to.setInCommentsOnly(from.isInCommentsOnly()); - to.setInStringLiteralsOnly(from.isInStringLiteralsOnly()); + to.setSearchContext(from.getSearchContext()); if (from.isReplaceState()) { to.setPreserveCase(from.isPreserveCase()); } diff --git a/platform/lang-impl/src/com/intellij/find/FindSettings.java b/platform/lang-impl/src/com/intellij/find/FindSettings.java index 964670a45723..d61fd395eadd 100644 --- a/platform/lang-impl/src/com/intellij/find/FindSettings.java +++ b/platform/lang-impl/src/com/intellij/find/FindSettings.java @@ -119,4 +119,13 @@ public abstract class FindSettings{ public abstract boolean isInCommentsOnly(); public abstract void setInCommentsOnly(boolean selected); + + public abstract boolean isExceptStringLiterals(); + public abstract void setExceptStringLiterals(boolean selected); + + public abstract boolean isExceptComments(); + public abstract void setExceptComments(boolean selected); + + public abstract boolean isExceptCommentsAndLiterals(); + public abstract void setExceptCommentsAndLiterals(boolean selected); } diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java new file mode 100644 index 000000000000..ae60f31a70b7 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java @@ -0,0 +1,38 @@ +/* + * 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.find.editorHeaderActions; + +import com.intellij.find.EditorSearchComponent; +import com.intellij.find.FindModel; +import com.intellij.openapi.actionSystem.AnActionEvent; + +public class ToggleExceptCommentsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction { + private static final String TEXT = "Except C&omments"; + + public ToggleExceptCommentsAction(EditorSearchComponent editorSearchComponent) { + super(editorSearchComponent, TEXT); + } + + @Override + public boolean isSelected(AnActionEvent e) { + return getEditorSearchComponent().getFindModel().isExceptComments(); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_COMMENTS : FindModel.SearchContext.ANY); + } +} diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java new file mode 100644 index 000000000000..ba7cc0e7be3e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java @@ -0,0 +1,38 @@ +/* + * 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.find.editorHeaderActions; + +import com.intellij.find.EditorSearchComponent; +import com.intellij.find.FindModel; +import com.intellij.openapi.actionSystem.AnActionEvent; + +public class ToggleExceptCommentsAndLiteralsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction { + private static final String TEXT = "Except Comments and Li&terals"; + + public ToggleExceptCommentsAndLiteralsAction(EditorSearchComponent editorSearchComponent) { + super(editorSearchComponent, TEXT); + } + + @Override + public boolean isSelected(AnActionEvent e) { + return getEditorSearchComponent().getFindModel().isExceptCommentsAndStringLiterals(); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_STRINGS_AND_COMMENTS : FindModel.SearchContext.ANY); + } +} diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java new file mode 100644 index 000000000000..c6c0c7901e82 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java @@ -0,0 +1,38 @@ +/* + * 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.find.editorHeaderActions; + +import com.intellij.find.EditorSearchComponent; +import com.intellij.find.FindModel; +import com.intellij.openapi.actionSystem.AnActionEvent; + +public class ToggleExceptLiteralsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction { + private static final String TEXT = "Except L&iterals"; + + public ToggleExceptLiteralsAction(EditorSearchComponent editorSearchComponent) { + super(editorSearchComponent, TEXT); + } + + @Override + public boolean isSelected(AnActionEvent e) { + return getEditorSearchComponent().getFindModel().isExceptStringLiterals(); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_STRINGS : FindModel.SearchContext.ANY); + } +} diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java index e6cae36868af..4d9d5ad44cac 100644 --- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java +++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java @@ -18,8 +18,6 @@ public class ToggleInCommentsAction extends EditorHeaderToggleAction implements @Override public void setSelected(AnActionEvent e, boolean state) { - FindModel findModel = getEditorSearchComponent().getFindModel(); - findModel.setInCommentsOnly(state); - if (state) findModel.setInStringLiteralsOnly(false); + getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.IN_COMMENTS : FindModel.SearchContext.ANY); } } diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java index c4d47e024f5e..9046c92412ac 100644 --- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java +++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java @@ -18,8 +18,6 @@ public class ToggleInLiteralsOnlyAction extends EditorHeaderToggleAction implem @Override public void setSelected(AnActionEvent e, boolean state) { - FindModel findModel = getEditorSearchComponent().getFindModel(); - findModel.setInStringLiteralsOnly(state); - if (state) findModel.setInCommentsOnly(false); + getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.IN_STRINGS : FindModel.SearchContext.ANY); } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java index b6a6152b678b..1182e133f62d 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.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. @@ -35,7 +35,6 @@ import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.*; -import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -50,8 +49,6 @@ import com.intellij.ui.EditorComboBoxRenderer; import com.intellij.ui.EditorTextField; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.StateRestoringCheckBox; -import com.intellij.ui.components.labels.LinkLabel; -import com.intellij.ui.components.labels.LinkListener; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.ui.UIUtil; @@ -60,7 +57,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.text.BadLocationException; import java.awt.*; import java.awt.event.*; import java.util.Arrays; @@ -78,8 +74,7 @@ public class FindDialog extends DialogWrapper { private StateRestoringCheckBox myCbCaseSensitive; private StateRestoringCheckBox myCbPreserveCase; private StateRestoringCheckBox myCbWholeWordsOnly; - private StateRestoringCheckBox myCbInCommentsOnly; - private StateRestoringCheckBox myCbInStringLiteralsOnly; + private ComboBox mySearchContext; private StateRestoringCheckBox myCbRegularExpressions; private JRadioButton myRbGlobal; private JRadioButton myRbSelectedText; @@ -476,6 +471,9 @@ public class FindDialog extends DialogWrapper { findSettings.setWholeWordsOnly(myModel.isWholeWordsOnly()); findSettings.setInStringLiteralsOnly(myModel.isInStringLiteralsOnly()); findSettings.setInCommentsOnly(myModel.isInCommentsOnly()); + findSettings.setExceptComments(myModel.isExceptComments()); + findSettings.setExceptStringLiterals(myModel.isExceptStringLiterals()); + findSettings.setExceptCommentsAndLiterals(myModel.isExceptCommentsAndStringLiterals()); findSettings.setRegularExpressions(myModel.isRegularExpressions()); if (!myModel.isMultipleFiles()){ @@ -603,39 +601,37 @@ public class FindDialog extends DialogWrapper { regExPanel.setLayout(new BoxLayout(regExPanel, BoxLayout.X_AXIS)); regExPanel.add(myCbRegularExpressions); - regExPanel.add(new LinkLabel("[Help]", null, new LinkListener() { - @Override - public void linkSelected(LinkLabel aSource, Object aLinkData) { - try { - final JBPopup helpPopup = RegExHelpPopup.createRegExHelpPopup(); - helpPopup.showInCenterOf(regExPanel); - } - catch (BadLocationException e) { - LOG.info(e); - } - } - })); + regExPanel.add(RegExHelpPopup.createRegExLink("[Help]", regExPanel, LOG)); findOptionsPanel.add(regExPanel); - myCbInCommentsOnly = createCheckbox(FindBundle.message("find.options.comments.only")); - myCbInStringLiteralsOnly = createCheckbox(FindBundle.message("find.options.string.literals.only")); - ItemListener itemListener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getSource() == myCbInCommentsOnly) { - if (myCbInCommentsOnly.isSelected()) myCbInStringLiteralsOnly.setSelected(false); - } else if (e.getSource() == myCbInStringLiteralsOnly) { - if (myCbInStringLiteralsOnly.isSelected()) myCbInCommentsOnly.setSelected(false); - } - } - }; - myCbInCommentsOnly.addItemListener(itemListener); - myCbInStringLiteralsOnly.addItemListener(itemListener); + mySearchContext = new ComboBox(new Object[] {FindBundle.message("find.context.anywhere.scope.label", 200), + FindBundle.message("find.context.in.comments.scope.label"), FindBundle.message("find.context.in.literals.scope.label"), + FindBundle.message("find.context.except.comments.scope.label"), + FindBundle.message("find.context.except.literals.scope.label"), + FindBundle.message("find.context.except.comments.and.literals.scope.label")}); + final JPanel searchContextPanel = new JPanel(new GridBagLayout()); + searchContextPanel.setAlignmentX(Component.LEFT_ALIGNMENT); + + GridBagConstraints gbConstraints = new GridBagConstraints(); + gbConstraints.fill = GridBagConstraints.HORIZONTAL; + gbConstraints.anchor = GridBagConstraints.WEST; + + gbConstraints.gridx = 0; + gbConstraints.gridy = 0; + gbConstraints.gridwidth = 1; + gbConstraints.weightx = 1; + + JLabel searchContextLabel = new JLabel(FindBundle.message("find.context.combo.label")); + searchContextLabel.setLabelFor(mySearchContext); + searchContextPanel.add(searchContextLabel, gbConstraints); + + ++gbConstraints.gridx; + + searchContextPanel.add(mySearchContext, gbConstraints); if (FindManagerImpl.ourHasSearchInCommentsAndLiterals) { - findOptionsPanel.add(myCbInCommentsOnly); - findOptionsPanel.add(myCbInStringLiteralsOnly); + findOptionsPanel.add(searchContextPanel); } ActionListener actionListener = new ActionListener() { @@ -1000,9 +996,25 @@ public class FindDialog extends DialogWrapper { } model.setWholeWordsOnly(myCbWholeWordsOnly.isSelected()); - model.setInStringLiteralsOnly(myCbInStringLiteralsOnly.isSelected()); - model.setInCommentsOnly(myCbInCommentsOnly.isSelected()); + String selectedSearchContextInUi = (String)mySearchContext.getSelectedItem(); + FindModel.SearchContext searchContext = FindModel.SearchContext.ANY; + if (FindBundle.message("find.context.in.literals.scope.label").equals(selectedSearchContextInUi)) { + searchContext = FindModel.SearchContext.IN_STRINGS; + } + else if (FindBundle.message("find.context.in.comments.scope.label").equals(selectedSearchContextInUi)) { + searchContext = FindModel.SearchContext.IN_COMMENTS; + } + else if (FindBundle.message("find.context.except.comments.scope.label").equals(selectedSearchContextInUi)) { + searchContext = FindModel.SearchContext.EXCEPT_COMMENTS; + } + else if (FindBundle.message("find.context.except.literals.scope.label").equals(selectedSearchContextInUi)) { + searchContext = FindModel.SearchContext.EXCEPT_STRINGS; + } else if (FindBundle.message("find.context.except.comments.and.literals.scope.label").equals(selectedSearchContextInUi)) { + searchContext = FindModel.SearchContext.EXCEPT_STRINGS_AND_COMMENTS; + } + + model.setSearchContext(searchContext); model.setRegularExpressions(myCbRegularExpressions.isSelected()); String stringToFind = getStringToFind(); @@ -1068,8 +1080,14 @@ public class FindDialog extends DialogWrapper { private void initByModel() { myCbCaseSensitive.setSelected(myModel.isCaseSensitive()); myCbWholeWordsOnly.setSelected(myModel.isWholeWordsOnly()); - myCbInStringLiteralsOnly.setSelected(myModel.isInStringLiteralsOnly()); - myCbInCommentsOnly.setSelected(myModel.isInCommentsOnly()); + String searchContext = FindBundle.message("find.context.anywhere.scope.label"); + if (myModel.isInCommentsOnly()) searchContext = FindBundle.message("find.context.in.comments.scope.label"); + else if (myModel.isInStringLiteralsOnly()) searchContext = FindBundle.message("find.context.in.literals.scope.label"); + else if (myModel.isExceptStringLiterals()) searchContext = FindBundle.message("find.context.except.literals.scope.label"); + else if (myModel.isExceptComments()) searchContext = FindBundle.message("find.context.except.literals.scope.label"); + else if (myModel.isExceptCommentsAndStringLiterals()) searchContext = FindBundle.message("find.context.except.comments.and.literals.scope.label"); + mySearchContext.setSelectedItem(searchContext); + myCbRegularExpressions.setSelected(myModel.isRegularExpressions()); if (myModel.isMultipleFiles()) { diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java index c243e1907500..bc99477ac08f 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java @@ -64,6 +64,7 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.ui.LightweightHint; import com.intellij.ui.ReplacePromptDialog; +import com.intellij.usages.ChunkExtractor; import com.intellij.usages.UsageViewManager; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; @@ -572,8 +573,8 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo final TextAttributesKey[] keys = activeSyntaxHighlighter.getTokenHighlights(tokenType); if (tokens.contains(tokenType) || - (model.isInStringLiteralsOnly() && isHighlightedAsString(keys)) || - (model.isInCommentsOnly() && isHighlightedAsDocComment(keys)) + (model.isInStringLiteralsOnly() && ChunkExtractor.isHighlightedAsString(keys)) || + (model.isInCommentsOnly() && ChunkExtractor.isHighlightedAsComment(keys)) ) { int start = lexer.getTokenStart(); int end = lexer.getTokenEnd(); @@ -646,32 +647,6 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo return prevFindResult; } - private static boolean isHighlightedAsDocComment(TextAttributesKey... keys) { - for (TextAttributesKey key : keys) { - if (key == DefaultLanguageHighlighterColors.DOC_COMMENT || key == SyntaxHighlighterColors.DOC_COMMENT) { - return true; - } - final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey(); - if (fallbackAttributeKey != null && isHighlightedAsDocComment(fallbackAttributeKey)) { - return true; - } - } - return false; - } - - private static boolean isHighlightedAsString(TextAttributesKey... keys) { - for (TextAttributesKey key : keys) { - if (key == DefaultLanguageHighlighterColors.STRING || key == SyntaxHighlighterColors.STRING) { - return true; - } - final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey(); - if (fallbackAttributeKey != null && isHighlightedAsString(fallbackAttributeKey)) { - return true; - } - } - return false; - } - private static TokenSet addTokenTypesForLanguage(FindModel model, Language lang, TokenSet tokensOfInterest) { ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(lang); if (definition != null) { diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java index 2c372795ea85..6baf8cc4fca8 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java @@ -110,7 +110,13 @@ public class FindResultUsageInfo extends UsageInfo { assert result.isStringFound(); - if (myFindModel.isRegularExpressions() || myFindModel.isInCommentsOnly() || myFindModel.isInStringLiteralsOnly()) { + if (myFindModel.isRegularExpressions() || + myFindModel.isInCommentsOnly() || + myFindModel.isInStringLiteralsOnly() || + myFindModel.isExceptStringLiterals() || + myFindModel.isExceptCommentsAndStringLiterals() || + myFindModel.isExceptComments() + ) { myAnchor = SmartPointerManager.getInstance(getProject()).createSmartPsiFileRangePointer(file, TextRange.from(offset, 0)); } diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java index 5fb74f190ac0..b96d14b08c59 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java @@ -103,6 +103,9 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom @SuppressWarnings({"WeakerAccess"}) public boolean WHOLE_WORDS_ONLY = false; @SuppressWarnings({"WeakerAccess"}) public boolean COMMENTS_ONLY = false; @SuppressWarnings({"WeakerAccess"}) public boolean STRING_LITERALS_ONLY = false; + @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_COMMENTS = false; + @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_COMMENTS_AND_LITERALS = false; + @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_LITERALS = false; @SuppressWarnings({"WeakerAccess"}) public boolean LOCAL_WHOLE_WORDS_ONLY = false; @SuppressWarnings({"WeakerAccess"}) public boolean REGULAR_EXPRESSIONS = false; @SuppressWarnings({"WeakerAccess"}) public boolean LOCAL_REGULAR_EXPRESSIONS = false; @@ -276,8 +279,18 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom model.setGlobal(isGlobal()); model.setRegularExpressions(isRegularExpressions()); model.setWholeWordsOnly(isWholeWordsOnly()); - model.setInCommentsOnly(isInCommentsOnly()); - model.setInStringLiteralsOnly(isInStringLiteralsOnly()); + FindModel.SearchContext searchContext = isInCommentsOnly() ? + FindModel.SearchContext.IN_COMMENTS : + isInStringLiteralsOnly() ? + FindModel.SearchContext.IN_STRINGS : + isExceptComments() ? + FindModel.SearchContext.EXCEPT_COMMENTS : + isExceptStringLiterals() ? + FindModel.SearchContext.EXCEPT_STRINGS : + isExceptCommentsAndLiterals() ? + FindModel.SearchContext.EXCEPT_STRINGS_AND_COMMENTS : + FindModel.SearchContext.ANY; + model.setSearchContext(searchContext); model.setWithSubdirectories(isWithSubdirectories()); model.setFileFilter(FILE_MASK); @@ -384,4 +397,34 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom public void setCustomScope(final String SEARCH_SCOPE) { this.SEARCH_SCOPE = SEARCH_SCOPE; } + + @Override + public boolean isExceptComments() { + return EXCEPT_COMMENTS; + } + + @Override + public void setExceptCommentsAndLiterals(boolean selected) { + EXCEPT_COMMENTS_AND_LITERALS = selected; + } + + @Override + public boolean isExceptCommentsAndLiterals() { + return EXCEPT_COMMENTS_AND_LITERALS; + } + + @Override + public void setExceptComments(boolean selected) { + EXCEPT_COMMENTS = selected; + } + + @Override + public boolean isExceptStringLiterals() { + return EXCEPT_LITERALS; + } + + @Override + public void setExceptStringLiterals(boolean selected) { + EXCEPT_LITERALS = selected; + } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java b/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java index 23dee12e362f..d93795419fb0 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java +++ b/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.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. @@ -17,12 +17,17 @@ package com.intellij.find.impl; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.ide.BrowserUtil; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ui.popup.ComponentPopupBuilder; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.util.MinimizeButton; import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.components.labels.LinkLabel; +import com.intellij.ui.components.labels.LinkListener; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.HyperlinkEvent; @@ -331,6 +336,22 @@ public class RegExHelpPopup extends JPanel { add(myScrollPane, BorderLayout.CENTER); } + @NotNull + public static LinkLabel createRegExLink(@NotNull String title, @Nullable final Component owner, @Nullable final Logger logger) { + return new LinkLabel(title, null, new LinkListener() { + @Override + public void linkSelected(LinkLabel aSource, Object aLinkData) { + try { + final JBPopup helpPopup = createRegExHelpPopup(); + helpPopup.showInCenterOf(owner); + } + catch (BadLocationException e) { + if (logger != null) logger.info(e); + } + } + }); + } + @Override public Dimension getPreferredSize() { return new Dimension(600, 300); diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java b/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java index e9e8c130a6f4..f5417dfb5a25 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterEx.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. @@ -116,7 +116,14 @@ public abstract class FormatterEx{ TextRange affectedRange); public abstract void setProgressTask(@NotNull FormattingProgressTask progressIndicator); - + + /** + * Calculates minimum spacing, allowed by formatting model (in columns) for a block starting at given offset, + * relative to its previous sibling block. + * Returns zero, if required block cannot be found at provided offset, or spacing cannot be calculated due to some other reason. + */ + public abstract int getSpacingForBlockAtOffset(FormattingModel model, int offset); + public interface IndentInfoStorage { void saveIndentInfo(@Nullable IndentInfo info, int startOffset); diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java index e1366431efd0..d28a68570e4d 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java @@ -25,6 +25,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; @@ -108,6 +109,58 @@ public class FormatterImpl extends FormatterEx myProgressTask.set(progressIndicator); } + @Override + public int getSpacingForBlockAtOffset(FormattingModel model, int offset) { + Couple blockWithParent = getBlockAtOffset(null, model.getRootBlock(), offset); + if (blockWithParent == null) { + return 0; + } + Block parentBlock = blockWithParent.first; + Block targetBlock = blockWithParent.second; + if (parentBlock == null || targetBlock == null) { + return 0; + } + Block prevBlock = findPreviousSibling(parentBlock, targetBlock); + if (prevBlock == null) { + return 0; + } + SpacingImpl spacing = (SpacingImpl)parentBlock.getSpacing(prevBlock, targetBlock); + if (spacing == null) { + return 0; + } + return spacing.getMinSpaces(); + } + + private static Couple getBlockAtOffset(Block parent, Block block, int offset) { + TextRange textRange = block.getTextRange(); + int startOffset = textRange.getStartOffset(); + int endOffset = textRange.getEndOffset(); + if (startOffset == offset) { + return Couple.of(parent, block); + } + if (startOffset > offset || endOffset < offset || block.isLeaf()) { + return null; + } + for (Block subBlock : block.getSubBlocks()) { + Couple result = getBlockAtOffset(block, subBlock, offset); + if (result != null) { + return result; + } + } + return null; + } + + private static Block findPreviousSibling(Block parent, Block block) { + Block result = null; + for (Block subBlock : parent.getSubBlocks()) { + if (subBlock == block) { + return result; + } + result = subBlock; + } + return null; + } + @Override public void format(final FormattingModel model, final CodeStyleSettings settings, final CommonCodeStyleSettings.IndentOptions indentOptions, diff --git a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java index bff04d06465e..ccf63a429346 100644 --- a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java +++ b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java @@ -100,8 +100,7 @@ public class GeneratedParserUtilBase { if (!goodMarker) return false; ErrorState state = ErrorState.get(builder_); - Frame frame = state.frameStack.peekLast(); - return frame == null || frame.errorReportedAt <= builder_.rawTokenIndex(); + return !state.frameStack.isEmpty(); } public static TokenSet create_token_set_(IElementType... tokenTypes_) { diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java index 72f9c5a965c0..330c084291fd 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.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. @@ -33,12 +33,14 @@ import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel; import com.intellij.openapi.roots.ui.componentsList.layout.VerticalStackLayout; import com.intellij.openapi.roots.ui.configuration.actions.IconWithTextAction; -import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.ex.VirtualFileManagerAdapter; +import com.intellij.ui.JBSplitter; import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.border.CustomLineBorder; import com.intellij.ui.roots.ToolbarPanel; import com.intellij.util.Consumer; import com.intellij.util.ui.UIUtil; @@ -48,6 +50,7 @@ import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import javax.swing.*; import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; @@ -146,7 +149,9 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor { myContentEntryEditorListener = new MyContentEntryEditorListener(); final JPanel mainPanel = new JPanel(new BorderLayout()); - mainPanel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6)); + if (!Registry.is("ide.new.project.settings")) { + mainPanel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6)); + } addAdditionalSettingsToPanel(mainPanel); @@ -159,21 +164,35 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor { myEditorsPanel = new ScrollablePanel(new VerticalStackLayout()); myEditorsPanel.setBackground(BACKGROUND_COLOR); - JScrollPane myScrollPane = ScrollPaneFactory.createScrollPane(myEditorsPanel); - entriesPanel.add(new ToolbarPanel(myScrollPane, group), BorderLayout.CENTER); + JScrollPane myScrollPane = ScrollPaneFactory.createScrollPane(myEditorsPanel, Registry.is("ide.new.project.settings")); + final ToolbarPanel toolbarPanel = new ToolbarPanel(myScrollPane, group); + if (Registry.is("ide.new.project.settings")) { + toolbarPanel.setBorder(new CustomLineBorder(1,0,0,0)); + } + entriesPanel.add(toolbarPanel, BorderLayout.CENTER); - final Splitter splitter = new Splitter(false); + final JBSplitter splitter = new JBSplitter(false); + if (Registry.is("ide.new.project.settings")) { + splitter.setOnePixelMode(); + } splitter.setProportion(0.6f); splitter.setHonorComponentsMinimumSize(true); myRootTreeEditor = createContentEntryTreeEditor(project); - splitter.setFirstComponent(myRootTreeEditor.createComponent()); + final JComponent component = myRootTreeEditor.createComponent(); + if (Registry.is("ide.new.project.settings")) { + component.setBorder(new CustomLineBorder(1,0,0,0)); + } + + splitter.setFirstComponent(component); splitter.setSecondComponent(entriesPanel); JPanel contentPanel = new JPanel(new GridBagLayout()); - contentPanel.setBorder(BorderFactory.createEtchedBorder()); + if (!Registry.is("ide.new.project.settings")) { + contentPanel.setBorder(BorderFactory.createEtchedBorder()); + } final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, myRootTreeEditor.getEditingActionsGroup(), true); contentPanel.add(new JLabel("Mark as:"), - new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(0, 5, 0, 5), 0, 0)); + new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(0, 10, 0, 10), 0, 0)); contentPanel.add(actionToolbar.getComponent(), new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); @@ -236,7 +255,11 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor { if (componentBorder != null) { border = BorderFactory.createCompoundBorder(border, componentBorder); } - component.setBorder(border); + if (Registry.is("ide.new.project.settings")) { + component.setBorder(new EmptyBorder(0,0,0,0)); + } else { + component.setBorder(border); + } myEditorsPanel.add(component); } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java index 469d966a29d8..bc10302c9c43 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.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. @@ -36,6 +36,7 @@ import com.intellij.ui.roots.IconActionComponent; import com.intellij.ui.roots.ResizingWrapper; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.util.NotNullProducer; import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -59,10 +60,22 @@ import java.util.Map; */ public abstract class ContentRootPanel extends JPanel { private static final Color EXCLUDED_COLOR = new JBColor(new Color(0x992E00), DarculaColors.RED); - private static final Color SELECTED_HEADER_COLOR = new JBColor(new Color(0xDEF2FF), UIUtil.getPanelBackground().darker()); + private static final Color SELECTED_HEADER_COLOR = new JBColor(new NotNullProducer() { + @NotNull + @Override + public Color produce() { + return UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground().darker() : new Color(0xDEF2FF); + } + }); private static final Color HEADER_COLOR = new JBColor(new Color(0xF5F5F5), Gray._82); private static final Color SELECTED_CONTENT_COLOR = new Color(0xF0F9FF); - private static final Color CONTENT_COLOR = new JBColor(Color.WHITE, UIUtil.getPanelBackground()); + private static final Color CONTENT_COLOR = new JBColor(new NotNullProducer() { + @NotNull + @Override + public Color produce() { + return UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground() : Gray._255; + } + }); private static final Color UNSELECTED_TEXT_COLOR = Gray._51; protected final ActionCallback myCallback; @@ -140,7 +153,7 @@ public abstract class ContentRootPanel extends JPanel { headerLabel.setFont(headerLabel.getFont().deriveFont(Font.BOLD)); headerLabel.setOpaque(false); if (getContentEntry().getFile() == null) { - headerLabel.setForeground(Color.RED); + headerLabel.setForeground(JBColor.RED); } final IconActionComponent deleteIconComponent = new IconActionComponent(AllIcons.Modules.DeleteContentRoot, AllIcons.Modules.DeleteContentRootRollover, diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java index 844b812ed26b..074e2a341825 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java @@ -1205,7 +1205,7 @@ public class SingleInspectionProfilePanel extends JPanel { } public JComponent getTree() { - return myTreeTable.getTree(); + return myTreeTable == null ? null : myTreeTable.getTree(); } private class MyFilterComponent extends FilterComponent { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 27089fa70e91..fdc434d8d11a 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -16,6 +16,7 @@ package com.intellij.psi.impl.source.tree.injected; +import com.intellij.extapi.psi.PsiFileBase; import com.intellij.injected.editor.*; import com.intellij.lang.Language; import com.intellij.lang.LanguageUtil; @@ -48,8 +49,10 @@ import java.util.List; * @author cdr */ public class InjectedLanguageUtil { - static final Key, TextRange>>> HIGHLIGHT_TOKENS = Key.create("HIGHLIGHT_TOKENS"); - public static Key FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION"); // meaning: injected file text is probably incorrect + static final Key, TextRange>>> HIGHLIGHT_TOKENS = + Key.create("HIGHLIGHT_TOKENS"); + public static Key FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION"); + // meaning: injected file text is probably incorrect public static void forceInjectionOnElement(@NotNull PsiElement host) { enumerate(host, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @@ -113,9 +116,9 @@ public class InjectedLanguageUtil { * @return true if enumerated successfully */ public static boolean enumerate(@NotNull PsiElement host, - @NotNull PsiFile containingFile, - boolean probeUp, - @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) { + @NotNull PsiFile containingFile, + boolean probeUp, + @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) { //do not inject into nonphysical files except during completion if (!containingFile.isPhysical() && containingFile.getOriginalFile() == containingFile) { final PsiElement context = InjectedLanguageManager.getInstance(containingFile.getProject()).getInjectionHost(containingFile); @@ -175,6 +178,32 @@ public class InjectedLanguageUtil { return null; } + /** + * Finds injected language in expression + * + * @param expression where to find + * @param classToFind class that represents language we look for + * @param class that represents language we look for + * @return instance of class that represents language we look for or null of not found + */ + @Nullable + @SuppressWarnings("unchecked") // We check types dynamically (using isAssignableFrom) + public static T findInjectedFile(@NotNull final PsiElement expression, + @NotNull final Class classToFind) { + final List> files = + InjectedLanguageManager.getInstance(expression.getProject()).getInjectedPsiFiles(expression); + if (files == null) { + return null; + } + for (final Pair fileInfo : files) { + final PsiElement injectedFile = fileInfo.first; + if (classToFind.isAssignableFrom(injectedFile.getClass())) { + return (T)injectedFile; + } + } + return null; + } + public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable PsiFile file, final int offset) { if (editor == null || file == null || editor instanceof EditorWindow) return editor; PsiFile injectedFile = findInjectedPsiNoCommit(file, offset); @@ -200,7 +229,9 @@ public class InjectedLanguageUtil { } } } - if (!documentWindow.isValid()) return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied + if (!documentWindow.isValid()) { + return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied + } return EditorWindowImpl.create(documentWindow, (EditorImpl)hostEditor, injectedFile); } @@ -284,7 +315,8 @@ public class InjectedLanguageUtil { ParameterizedCachedValue cachedValue = CachedValuesManager.getManager(project).createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false); - CachedValueProvider.Result result = CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar); + CachedValueProvider.Result result = + CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar); ((PsiParameterizedCachedValue)cachedValue).setValue(result); e.putUserData(INJECTED_PSI, cachedValue); @@ -307,7 +339,9 @@ public class InjectedLanguageUtil { // returns (injected psi, leaf element at the offset, language of the leaf element) // since findElementAt() is expensive, we trying to reuse its result @NotNull - private static Trinity tryOffset(@NotNull PsiFile hostFile, final int offset, @NotNull PsiDocumentManager documentManager) { + private static Trinity tryOffset(@NotNull PsiFile hostFile, + final int offset, + @NotNull PsiDocumentManager documentManager) { FileViewProvider provider = hostFile.getViewProvider(); Language leafLanguage = null; PsiElement leafElement = null; @@ -319,11 +353,11 @@ public class InjectedLanguageUtil { leafElement = element; } PsiElement injected = findInside(element, hostFile, offset, documentManager); - if (injected != null) return Trinity.create(injected,element, language); + if (injected != null) return Trinity.create(injected, element, language); } // maybe we are at the border between two psi elements, then try to find injection at the end of the left element if (offset != 0 && (element == null || element.getTextRange().getStartOffset() == offset)) { - PsiElement leftElement = provider.findElementAt(offset-1, language); + PsiElement leftElement = provider.findElementAt(offset - 1, language); if (leftElement != null && leftElement.getTextRange().getEndOffset() == offset) { PsiElement injected = findInside(leftElement, hostFile, offset, documentManager); if (injected != null) return Trinity.create(injected, element, language); @@ -334,7 +368,10 @@ public class InjectedLanguageUtil { return Trinity.create(null, leafElement, leafLanguage); } - private static PsiElement findInside(@NotNull PsiElement element, @NotNull PsiFile hostFile, final int hostOffset, @NotNull final PsiDocumentManager documentManager) { + private static PsiElement findInside(@NotNull PsiElement element, + @NotNull PsiFile hostFile, + final int hostOffset, + @NotNull final PsiDocumentManager documentManager) { final Ref out = new Ref(); enumerate(element, hostFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override @@ -361,10 +398,12 @@ public class InjectedLanguageUtil { // modification of cachedInjectedDocuments must be under PsiLock only ConcurrentList injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY); if (injected == null) { - injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.createConcurrentList()); + injected = + ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.createConcurrentList()); } return injected; } + public static void clearCachedInjectedFragmentsForFile(@NotNull PsiFile file) { file.putUserData(INJECTED_DOCS_KEY, null); } @@ -426,10 +465,12 @@ public class InjectedLanguageUtil { } return containingFile; } + @NotNull public static Editor getTopLevelEditor(@NotNull Editor editor) { return editor instanceof EditorWindow ? ((EditorWindow)editor).getDelegate() : editor; } + public static boolean isInInjectedLanguagePrefixSuffix(@NotNull final PsiElement element) { PsiFile injectedFile = element.getContainingFile(); if (injectedFile == null) return false; @@ -461,13 +502,13 @@ public class InjectedLanguageUtil { public static String getUnescapedText(PsiFile file, @Nullable final PsiElement startElement, @Nullable final PsiElement endElement) { final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(file.getProject()); if (manager.getInjectionHost(file) == null) { - return file.getText().substring(startElement == null? 0 : startElement.getTextRange().getStartOffset(), - endElement == null? file.getTextLength() : endElement.getTextRange().getStartOffset()); + return file.getText().substring(startElement == null ? 0 : startElement.getTextRange().getStartOffset(), + endElement == null ? file.getTextLength() : endElement.getTextRange().getStartOffset()); } final StringBuilder sb = new StringBuilder(); file.accept(new PsiRecursiveElementWalkingVisitor() { - Boolean myState = startElement == null? Boolean.TRUE : null; + Boolean myState = startElement == null ? Boolean.TRUE : null; @Override public void visitElement(PsiElement element) { diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java index cb281cb3d7af..d33bf51e9002 100644 --- a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java +++ b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java @@ -8,6 +8,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.HyperlinkAdapter; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBLabel; +import com.intellij.util.ObjectUtils; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,6 +34,7 @@ public class PackagesNotificationPanel { myEditorPane.setBackground(UIManager.getColor("ArrowButton.background")); myEditorPane.setContentType("text/html"); myEditorPane.setEditable(false); + myEditorPane.setVisible(false); myEditorPane.addHyperlinkListener(new HyperlinkAdapter() { @Override protected void hyperlinkActivated(HyperlinkEvent e) { @@ -104,11 +106,10 @@ public class PackagesNotificationPanel { } private void showContent(String text, final Color background) { - myEditorPane.removeAll(); String htmlText = text.startsWith("") ? text : UIUtil.toHtml(text); myEditorPane.setText(htmlText); myEditorPane.setBackground(background); - myEditorPane.setVisible(true); + setVisibleEditorPane(true); myErrorTitle = null; myErrorDescription = null; } @@ -124,7 +125,20 @@ public class PackagesNotificationPanel { } public void hide() { - myEditorPane.setVisible(false); + setVisibleEditorPane(false); + } + + private void setVisibleEditorPane(boolean visible) { + boolean oldVisible = myEditorPane.isVisible(); + myEditorPane.setVisible(visible); + if (oldVisible != visible) { + JComponent comp = ObjectUtils.tryCast(myEditorPane.getParent(), JComponent.class); + if (comp == null) { + comp = myEditorPane; + } + comp.revalidate(); + comp.repaint(); + } } public boolean hasLinkHandler(String key) { diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java new file mode 100644 index 000000000000..3284439c1b24 --- /dev/null +++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java @@ -0,0 +1,3 @@ +class Foo { + int i; +} diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java new file mode 100644 index 000000000000..25766081e3c2 --- /dev/null +++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java @@ -0,0 +1,4 @@ +class Foo { + int + i; +} diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java new file mode 100644 index 000000000000..3284439c1b24 --- /dev/null +++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java @@ -0,0 +1,3 @@ +class Foo { + int i; +} diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java new file mode 100644 index 000000000000..29e2260c35b8 --- /dev/null +++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java @@ -0,0 +1,4 @@ +class Foo { + int + i; +} diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java new file mode 100644 index 000000000000..3284439c1b24 --- /dev/null +++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java @@ -0,0 +1,3 @@ +class Foo { + int i; +} diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java new file mode 100644 index 000000000000..6c1bbe85b269 --- /dev/null +++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java @@ -0,0 +1,4 @@ +class Foo { + int +i; +} diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index 0b15c99a57b3..cd1d1b0dba49 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -150,6 +150,9 @@ public class BrowserUtil { else if (SystemInfo.isMac) { return "open"; } + else if (SystemInfo.isUnix) { + return "/usr/bin/firefox"; + } else { return ""; } diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java index f81cb852046d..736dcd8afe22 100644 --- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java +++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java @@ -74,10 +74,10 @@ public class BrowserLauncherAppless extends BrowserLauncher { Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action); } - public static boolean canStartDefaultBrowser() { + public static boolean canUseSystemDefaultBrowserPolicy() { return isDesktopActionSupported(Desktop.Action.BROWSE) || SystemInfo.isMac || SystemInfo.isWindows || - SystemInfo.isUnix && SystemInfo.hasXdgOpen(); + (SystemInfo.isUnix && SystemInfo.hasXdgOpen()); } private static GeneralSettings getGeneralSettingsInstance() { @@ -145,6 +145,10 @@ public class BrowserLauncherAppless extends BrowserLauncher { } } + browseUsingNotSystemDefaultBrowserPolicy(uri, settings, project); + } + + protected void browseUsingNotSystemDefaultBrowserPolicy(@NotNull URI uri, @NotNull GeneralSettings settings, @Nullable Project project) { browseUsingPath(uri.toString(), settings.getBrowserPath(), null, project, ArrayUtil.EMPTY_STRING_ARRAY); } diff --git a/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java index 38b26077f6df..555097bb546c 100644 --- a/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java +++ b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java @@ -88,6 +88,7 @@ public final class ChromeSettings extends BrowserSpecificSettings { return cliOptions; } + @Override @NotNull @Tag("environment-variables") @MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false) @@ -105,8 +106,9 @@ public final class ChromeSettings extends BrowserSpecificSettings { return new ChromeSettingsConfigurable(this); } + @Override public ChromeSettings clone() { - final ChromeSettings clone = (ChromeSettings)super.clone(); + ChromeSettings clone = (ChromeSettings)super.clone(); clone.myEnvironmentVariables = myEnvironmentVariables.clone(); return clone; } diff --git a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java index ef95f7cb872e..c28b7e495b41 100644 --- a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java +++ b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java @@ -26,7 +26,6 @@ import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.DocumentAdapter; -import com.intellij.util.ObjectUtils; import com.intellij.util.PathUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.Nullable; @@ -48,7 +47,7 @@ public class FirefoxSettingsConfigurable implements Configurable { private final FirefoxSettings mySettings; private String myLastProfilesIniPath; private String myDefaultProfilesIniPath; - private String myDefaultProfile; + private String defaultProfile; public FirefoxSettingsConfigurable(FirefoxSettings settings) { mySettings = settings; @@ -89,11 +88,8 @@ public class FirefoxSettingsConfigurable implements Configurable { @Nullable private String getConfiguredProfileName() { - final String selected = (String)myProfileCombobox.getSelectedItem(); - if (Comparing.equal(myDefaultProfile, selected)) { - return null; - } - return selected; + String selected = (String)myProfileCombobox.getSelectedItem(); + return Comparing.equal(defaultProfile, selected) ? null : selected; } @Override @@ -110,7 +106,9 @@ public class FirefoxSettingsConfigurable implements Configurable { String path = mySettings.getProfilesIniPath(); myProfilesIniPathField.setText(path != null ? FileUtilRt.toSystemDependentName(path) : myDefaultProfilesIniPath); updateProfilesList(); - myProfileCombobox.setSelectedItem(ObjectUtils.notNull(mySettings.getProfile(), myDefaultProfile)); + + String profile = mySettings.getProfile(); + myProfileCombobox.setSelectedItem(profile == null ? defaultProfile : profile); } private void updateProfilesList() { @@ -122,7 +120,7 @@ public class FirefoxSettingsConfigurable implements Configurable { myProfileCombobox.removeAllItems(); final List profiles = FirefoxUtil.computeProfiles(new File(profilesIniPath)); final FirefoxProfile defaultProfile = FirefoxUtil.getDefaultProfile(profiles); - myDefaultProfile = defaultProfile != null ? defaultProfile.getName() : null; + this.defaultProfile = defaultProfile != null ? defaultProfile.getName() : null; for (FirefoxProfile profile : profiles) { //noinspection unchecked myProfileCombobox.addItem(profile.getName()); diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java index 78f07a04b4a9..e2c9175ac915 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java @@ -16,6 +16,7 @@ package com.intellij.openapi.diff; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -59,4 +60,12 @@ public abstract class DiffRequestFactory { Project project, @Nullable ActionButtonPresentation okButtonPresentation, @Nullable ActionButtonPresentation cancelButtonPresentation); + + public abstract MergeRequest create3WayDiffRequest(String leftText, + String rightText, + String originalContent, + @Nullable FileType type, + Project project, + @Nullable ActionButtonPresentation okButtonPresentation, + @Nullable ActionButtonPresentation cancelButtonPresentation); } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java index 655854ac933c..b0df0917dfe0 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java @@ -240,7 +240,7 @@ class DragHelper extends MouseDragHelper { final JBTabsPosition position = myTabs.getTabsPosition(); - if (!willDragOutStart && JBEditorTabs.isAlphabeticalMode() && position != JBTabsPosition.top && position != JBTabsPosition.bottom) { + if (!willDragOutStart && myTabs.isAlphabeticalMode() && position != JBTabsPosition.top && position != JBTabsPosition.bottom) { Point p = new Point(event.getPoint()); p = SwingUtilities.convertPoint(event.getComponent(), p, myTabs); if (myTabs.getVisibleRect().contains(p) && myPressedOnScreenPoint.distance(new RelativePoint(event).getScreenPoint()) > 15) { diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java index 761d3ea0d341..8e5844fd4684 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java @@ -43,7 +43,7 @@ import java.util.List; * @author pegov */ public class JBEditorTabs extends JBTabsImpl { - private static final String TABS_ALPHABETICAL_KEY = "tabs.alphabetical"; + public static final String TABS_ALPHABETICAL_KEY = "tabs.alphabetical"; private JBEditorTabsPainter myDarkPainter = new DarculaEditorTabsPainter(); private JBEditorTabsPainter myDefaultPainter = new DefaultEditorTabsPainter(); @@ -130,7 +130,7 @@ public class JBEditorTabs extends JBTabsImpl { return UIUtil.isUnderDarcula() ? myDarkPainter : myDefaultPainter; } - public static boolean isAlphabeticalMode() { + public boolean isAlphabeticalMode() { return Registry.is(TABS_ALPHABETICAL_KEY); } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index c5ecbbe3b6f8..60898a6e9bd8 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -1262,6 +1262,10 @@ public class JBTabsImpl extends JComponent return null; } + public boolean isAlphabeticalMode() { + return false; + } + @Nullable private TabInfo findEnabledBackward(int from, boolean cycle) { if (from < 0) return null; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java index 653420ae261f..4e5925d2a2ee 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.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. @@ -147,7 +147,7 @@ public class SingleRowLayout extends TabLayout { } public LayoutPassInfo layoutSingleRow(List visibleInfos) { - if (JBEditorTabs.isAlphabeticalMode()) { + if (myTabs.isAlphabeticalMode()) { Collections.sort(visibleInfos, new Comparator() { @Override public int compare(TabInfo o1, TabInfo o2) { diff --git a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java index 669766ee104b..3000b49656c6 100644 --- a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java +++ b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java @@ -29,7 +29,7 @@ public abstract class HttpRequestHandler { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.httpRequestHandler"); public boolean isSupported(@NotNull FullHttpRequest request) { - return request.getMethod() == HttpMethod.GET || request.getMethod() == HttpMethod.HEAD; + return request.method() == HttpMethod.GET || request.method() == HttpMethod.HEAD; } public abstract boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) diff --git a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java index e3e1945d14f1..3b8bacee5457 100644 --- a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java @@ -59,7 +59,7 @@ public class XmlRpcServerImpl implements XmlRpcServer { static final class XmlRpcRequestHandler extends HttpRequestHandler { @Override public boolean isSupported(@NotNull FullHttpRequest request) { - return request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS; + return request.method() == HttpMethod.POST || request.method() == HttpMethod.OPTIONS; } @Override @@ -89,7 +89,7 @@ public class XmlRpcServerImpl implements XmlRpcServer { return false; } - if (request.getMethod() == HttpMethod.POST) { + if (request.method() == HttpMethod.POST) { ByteBuf result; ByteBufInputStream in = new ByteBufInputStream(request.content()); try { @@ -116,7 +116,7 @@ public class XmlRpcServerImpl implements XmlRpcServer { return true; } else if (HttpMethod.POST.name().equals(request.headers().get("Access-Control-Request-Method"))) { - LOG.assertTrue(request.getMethod() == HttpMethod.OPTIONS); + LOG.assertTrue(request.method() == HttpMethod.OPTIONS); Responses.sendOptionsResponse("POST, OPTIONS", request, context); return true; } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java b/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java index 8431364c5d61..7b000f530bdf 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.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. @@ -18,6 +18,7 @@ package com.intellij.ide.actions; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.ToggleAction; +import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.tabs.impl.JBEditorTabs; import javax.swing.*; @@ -28,7 +29,7 @@ import javax.swing.*; public class TabsAlphabeticalModeSwitcher extends ToggleAction { @Override public boolean isSelected(AnActionEvent e) { - return JBEditorTabs.isAlphabeticalMode(); + return Registry.is(JBEditorTabs.TABS_ALPHABETICAL_KEY); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index 24255197e301..3baff07649aa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -297,13 +297,11 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid myData.setContents(content1, content2); Project project = myData.getProject(); FileType[] types = DiffUtil.chooseContentTypes(new DiffContent[]{content1, content2}); - VirtualFile baseFile = content1.getFile(); - if (baseFile == null && myDiffRequest != null) { - String path = myDiffRequest.getWindowTitle(); - if (path != null) baseFile = LocalFileSystem.getInstance().findFileByPath(path); - } - myLeftSide.setHighlighterFactory(createHighlighter(types[0], baseFile, project)); - myRightSide.setHighlighterFactory(createHighlighter(types[1], baseFile, project)); + VirtualFile beforeFile = content1.getFile(); + VirtualFile afterFile = content2.getFile(); + String path = myDiffRequest == null ? null : myDiffRequest.getWindowTitle(); + myLeftSide.setHighlighterFactory(createHighlighter(types[0], beforeFile, afterFile, path, project)); + myRightSide.setHighlighterFactory(createHighlighter(types[1], afterFile, beforeFile, path, project)); setSplitterProportion(content1, content2); rediff(); if (myIsRequestFocus) { @@ -343,8 +341,16 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid } } // todo pay attention here - private static DiffHighlighterFactory createHighlighter(FileType contentType, VirtualFile file, Project project) { - return new DiffHighlighterFactoryImpl(contentType, file, project); + private static DiffHighlighterFactory createHighlighter(FileType contentType, + VirtualFile file, + VirtualFile otherFile, + String path, + Project project) { + VirtualFile baseFile = file; + if (baseFile == null) baseFile = otherFile; + if (baseFile == null && path != null) baseFile = LocalFileSystem.getInstance().findFileByPath(path); + + return new DiffHighlighterFactoryImpl(contentType, baseFile, project); } void rediff() { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java index 10362cc8b304..091ac47c7251 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java @@ -27,9 +27,7 @@ import com.intellij.openapi.diff.*; import com.intellij.openapi.diff.actions.NextDiffAction; import com.intellij.openapi.diff.actions.PreviousDiffAction; import com.intellij.openapi.diff.actions.ToggleAutoScrollAction; -import com.intellij.openapi.diff.impl.DiffUtil; -import com.intellij.openapi.diff.impl.EditingSides; -import com.intellij.openapi.diff.impl.GenericDataProvider; +import com.intellij.openapi.diff.impl.*; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.diff.impl.incrementalMerge.ChangeCounter; import com.intellij.openapi.diff.impl.incrementalMerge.ChangeList; @@ -49,16 +47,20 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.EditorMarkupModel; +import com.intellij.openapi.editor.highlighter.EditorHighlighter; import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogBuilder; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.LabeledComponent; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.EditorNotificationPanel; -import com.intellij.util.diff.FilesTooBigForDiffException; +import com.intellij.util.containers.Convertor; import gnu.trove.TIntHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -235,6 +237,8 @@ public class MergePanel2 implements DiffViewer { Editor base = getEditor(1); Editor right = getEditor(2); + setupHighlighterSettings(left, base, right); + myMergeList.setMarkups(left, base, right); EditingSides[] sides = {getFirstEditingSide(), getSecondEditingSide()}; myScrollSupport.install(sides); @@ -271,6 +275,37 @@ public class MergePanel2 implements DiffViewer { return myScrollSupport.isEnabled(); } + private void setupHighlighterSettings(Editor left, Editor base, Editor right) { + Editor[] editors = new Editor[]{left, base, right}; + DiffContent[] contents = myData.getContents(); + FileType[] types = DiffUtil.chooseContentTypes(contents); + + VirtualFile fallbackFile = contents[1].getFile(); + FileType fallbackType = contents[1].getContentType(); + + for (int i = 0; i < 3; i++) { + Editor editor = editors[i]; + DiffContent content = contents[i]; + + EditorHighlighter highlighter = + createHighlighter(types[i], content.getFile(), fallbackFile, fallbackType, myData.getProject()).createHighlighter(); + if (highlighter != null) { + ((EditorEx)editor).setHighlighter(highlighter); + } + } + } + + private static DiffHighlighterFactory createHighlighter(FileType contentType, + VirtualFile file, + VirtualFile otherFile, + FileType otherType, + Project project) { + if (file == null) file = otherFile; + if (contentType == null) contentType = otherType; + + return new DiffHighlighterFactoryImpl(contentType, file, project); + } + public void setHighlighterSettings(@Nullable EditorColorsScheme settings) { for (EditorPlace place : getEditorPlaces()) { setHighlighterSettings(settings, place); @@ -337,7 +372,20 @@ public class MergePanel2 implements DiffViewer { data.customizeToolbar(myPanel.resetToolbar()); myPanel.registerToolbarActions(); if ( data instanceof MergeRequestImpl && myBuilder != null){ - ((MergeRequestImpl)data).setActions(myBuilder, this); + Convertor preOkHook = new Convertor() { + @Override + public Boolean convert(DialogWrapper dialog) { + ChangeCounter counter = ChangeCounter.getOrCreate(myMergeList); + int changes = counter.getChangeCounter(); + int conflicts = counter.getConflictCounter(); + if (changes == 0 && conflicts == 0) return true; + return Messages.showYesNoDialog(dialog.getRootPane(), + DiffBundle.message("merge.dialog.apply.partially.resolved.changes.confirmation.message", changes, conflicts), + DiffBundle.message("apply.partially.resolved.merge.dialog.title"), + Messages.getQuestionIcon()) == Messages.YES; + } + }; + ((MergeRequestImpl)data).setActions(myBuilder, this, preOkHook); } } finally { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java index 3b13543e6972..221a082d5367 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java @@ -20,6 +20,7 @@ import com.intellij.openapi.diff.DiffRequestFactory; import com.intellij.openapi.diff.MergeRequest; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -41,16 +42,29 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { cancelButtonPresentation); } else { - return create3WayDiffRequest(leftText, rightText, originalContent, project, okButtonPresentation, cancelButtonPresentation); + return create3WayDiffRequest(leftText, rightText, originalContent, file.getFileType(), project, okButtonPresentation, cancelButtonPresentation); } } + public MergeRequest create3WayDiffRequest(final String leftText, + final String rightText, + final String originalContent, + @Nullable FileType type, + final Project project, + @Nullable final ActionButtonPresentation okButtonPresentation, + @Nullable final ActionButtonPresentation cancelButtonPresentation) { + if (type != null) { + return new MergeRequestImpl(leftText, originalContent, rightText, type, project, okButtonPresentation, cancelButtonPresentation); + } + return new MergeRequestImpl(leftText, originalContent, rightText, project, okButtonPresentation, cancelButtonPresentation); + } + public MergeRequest create3WayDiffRequest(final String leftText, final String rightText, final String originalContent, final Project project, @Nullable final ActionButtonPresentation okButtonPresentation, @Nullable final ActionButtonPresentation cancelButtonPresentation) { - return new MergeRequestImpl(leftText, originalContent, rightText, project, okButtonPresentation, cancelButtonPresentation); + return create3WayDiffRequest(leftText, rightText, originalContent, null, project, okButtonPresentation, cancelButtonPresentation); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java index 3b1385eb7a59..f6642b720acc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java @@ -28,6 +28,7 @@ import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.Convertor; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -75,6 +76,19 @@ public class MergeRequestImpl extends MergeRequest { cancelButtonPresentation); } + public MergeRequestImpl(String left, + String base, + String right, + FileType type, + Project project, + @Nullable final ActionButtonPresentation okButtonPresentation, + @Nullable final ActionButtonPresentation cancelButtonPresentation) { + this(new SimpleContent(left, type), + new SimpleContent(base, type), + new SimpleContent(right, type), + project, okButtonPresentation, cancelButtonPresentation); + } + private MergeRequestImpl(DiffContent left, DiffContent base, DiffContent right, @@ -176,6 +190,10 @@ public class MergeRequestImpl extends MergeRequest { } public void setActions(final DialogBuilder builder, MergePanel2 mergePanel) { + setActions(builder, mergePanel, null); + } + + public void setActions(final DialogBuilder builder, MergePanel2 mergePanel, final Convertor preOkHook) { builder.removeAllActions(); // otherwise dialog will get default actions (OK, Cancel) if (myOkButtonPresentation != null) { @@ -187,6 +205,7 @@ public class MergeRequestImpl extends MergeRequest { builder.setOkOperation(new Runnable() { @Override public void run() { + if (preOkHook != null && !preOkHook.convert(builder.getDialogWrapper())) return; myOkButtonPresentation.run(builder.getDialogWrapper()); } }); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index f600c606a98d..39706f016adc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -992,7 +992,16 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } public void setLineNumberAreaWidth(@NotNull TIntFunction calculator) { - final int lineNumberAreaWidth = calculator.execute(myLineNumberConvertor.execute(endLineNumber())); + int maxLineNumber = 0; + for (int i = endLineNumber(); i >= 0; i--) { + int number = myLineNumberConvertor.execute(i); + if (number >= 0) { + maxLineNumber = number; + break; + } + } + + final int lineNumberAreaWidth = calculator.execute(maxLineNumber); if (myLineNumberAreaWidth != lineNumberAreaWidth) { myLineNumberAreaWidth = lineNumberAreaWidth; fireResized(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index e36a120d609b..c7fa51f770d1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -227,7 +227,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec fm.doWhenFocusSettlesDown(run); } else { - run.run(); + UIUtil.invokeAndWaitIfNeeded(run); } return result; diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index c6c209ed4b88..b73b8ed522ea 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -200,8 +200,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { if (cmp == myCloseRec) return true; if (UIUtil.isDescendingFrom(cmp, myComp)) return true; if (myComp == null || !myComp.isShowing()) return false; - Rectangle rectangleOnScreen = new Rectangle(myComp.getLocationOnScreen(), myComp.getSize()); - return rectangleOnScreen.contains(target.getScreenPoint()); + return myComp.contains(target.getScreenPoint().x, target.getScreenPoint().y); } public boolean isMovingForward(RelativePoint target) { diff --git a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java index 162ff8288049..d5fc8dcca1ba 100644 --- a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java @@ -40,6 +40,11 @@ public class JBTabsPaneImpl implements TabbedPane, SwingConstants { public JBTabsPaneImpl(@Nullable Project project, int tabPlacement, @NotNull Disposable parent) { myTabs = new JBEditorTabs(project, ActionManager.getInstance(), project == null ? null : IdeFocusManager.getInstance(project), parent) { + @Override + public boolean isAlphabeticalMode() { + return false; + } + @Override protected void doPaintBackground(Graphics2D g2d, Rectangle clip) { super.doPaintBackground(g2d, clip); @@ -60,7 +65,7 @@ public class JBTabsPaneImpl implements TabbedPane, SwingConstants { maxOffset++; g2d.setPaint(UIUtil.getPanelBackground()); g2d.fillRect(clip.x + maxOffset, clip.y, clip.width - maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT); - g2d.setPaint(new JBColor(Gray._181, Gray._158)); + g2d.setPaint(new JBColor(Gray._181, UIUtil.getPanelBackground())); g2d.drawLine(clip.x + maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT, clip.x + clip.width, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT); g2d.setPaint(UIUtil.getPanelBackground()); g2d.drawLine(clip.x, clip.y + maxLength, clip.width, clip.y + maxLength); diff --git a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java index a7d09ab548f2..7310b936246d 100644 --- a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java +++ b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java @@ -170,7 +170,7 @@ public class BuiltInServer implements Disposable { @Override protected boolean process(ChannelHandlerContext context, FullHttpRequest request, QueryStringDecoder urlDecoder) throws IOException { - return (request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS) && + return (request.method() == HttpMethod.POST || request.method() == HttpMethod.OPTIONS) && XmlRpcServer.SERVICE.getInstance().process(urlDecoder.path(), request, context, handlers); } } diff --git a/platform/platform-resources-en/src/messages/DiffBundle.properties b/platform/platform-resources-en/src/messages/DiffBundle.properties index 598cc9714697..aafd6884a3d6 100644 --- a/platform/platform-resources-en/src/messages/DiffBundle.properties +++ b/platform/platform-resources-en/src/messages/DiffBundle.properties @@ -67,6 +67,8 @@ merge.partial.diff.action.name.0.1=Compare left and middle panel contents merge.partial.diff.action.name.1.2=Compare middle and right panel contents merge.dialog.exit.without.applying.changes.confirmation.message=Are you sure you want to exit without applying changes? cancel.visual.merge.dialog.title=Cancel Visual Merge +merge.dialog.apply.partially.resolved.changes.confirmation.message=There are {0, choice, 0#|1#one change|2#{0, number} changes}{0, choice, 0#|1#'{1, choice, 0#|1# and }'}{1, choice, 0#|1#one conflict|2#{1, number} conflicts} left unprocessed.\nAre you sure you want to save changes and finish merging? +apply.partially.resolved.merge.dialog.title=Apply Changes merge.all.changes.have.processed.save.and.finish.confirmation.text=All changes have been processed.\nWould you like to save changes and finish merging? all.changes.processed.dialog.title=All Changes Processed merge.save.and.finish.button=Save and &Finish diff --git a/platform/platform-resources-en/src/messages/FindBundle.properties b/platform/platform-resources-en/src/messages/FindBundle.properties index 293d013fe8d6..b532e73e0a48 100644 --- a/platform/platform-resources-en/src/messages/FindBundle.properties +++ b/platform/platform-resources-en/src/messages/FindBundle.properties @@ -69,6 +69,14 @@ find.text.to.find.label=Text to &find: find.replace.with.label=Replace &with: find.filter.file.name.group=File name filter find.filter.file.mask.checkbox=File m&ask(s) +find.context.combo.label=Conte&xt: +find.context.anywhere.scope.label=anywhere +find.context.in.comments.scope.label=in comments +find.context.in.literals.scope.label=in string literals +find.context.except.literals.scope.label=except string literals +find.context.except.comments.scope.label=except comments +find.context.except.comments.and.literals.scope.label=except comments and string literals + find.directory.not.found.error=Directory {0} is not found find.invalid.regular.expression.error=Bad pattern \"{0}\": {1} find.empty.match.regular.expression.error=Regular expression matches empty string diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java index a90148799f5d..dbc05f849a49 100644 --- a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java +++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java @@ -202,42 +202,22 @@ public class ReformatFilesWithFiltersTest extends LightPlatformTestCase { TestFileStructure fileTree = new TestFileStructure(getModule(), myWorkingDirectory); fileTree.createDirectoryAndMakeItCurrent("src"); - PsiFile java2 = fileTree.addTestFile("Test2.java", "empty content"); + PsiFile java2 = fileTree.addTestFile("Test2.tj", "empty content"); PsiFile php2 = fileTree.addTestFile("Pair2.php", "empty content"); PsiFile js2 = fileTree.addTestFile("Pair2.js", "empty content"); PsiDirectory test = fileTree.createDirectoryAndMakeItCurrent("test"); - PsiFile testJava1 = fileTree.addTestFile("testJava1.java", "empty content"); + PsiFile testJava1 = fileTree.addTestFile("testJava1.tj", "empty content"); PsiFile testPhp1 = fileTree.addTestFile("testPhp1.php", "empty content"); PsiFile testJs1 = fileTree.addTestFile("testJs1.js", "empty content"); GlobalSearchScope testScope = directoryScope(test, true); - Logger logger = Logger.getInstance(getClass()); - logFiles(logger, "Previously formatted files: ", myMockCodeStyleManager.getFormattedFiles()); - - reformatWithRearrange(myWorkingDirectory, testScope); - logFiles(logger, "Currently formatted files: ", myMockCodeStyleManager.getFormattedFiles()); - logFiles(logger, "Should be formatted", ContainerUtil.newArrayList(testJava1, testPhp1, testJs1)); - - assertWasFormatted(testJava1, testPhp1, testJs1); - assertWasNotFormatted(java2, php2, js2); - reformatAndOptimize(myWorkingDirectory, testScope); assertWasFormatted(testJava1, testPhp1, testJs1); assertWasNotFormatted(java2, php2, js2); } - private void logFiles(Logger log, String message, Collection files) { - StringBuilder builder; - builder = new StringBuilder(); - builder.append(message).append('\n'); - for (PsiFile file : files) { - builder.append(file).append('\n'); - } - log.info(builder.toString()); - } - public void assertWasFormatted(PsiFile... files) { final Set formattedFiles = myMockCodeStyleManager.getFormattedFiles(); for (PsiFile file : files) { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java index 7a8e9ca01922..fa901849867f 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java @@ -522,10 +522,8 @@ public class LibraryImpl extends TraceableDisposable implements LibraryEx.Modifi private boolean isUnderRoots(@NotNull String url) { for (VirtualFilePointerContainer container : myRoots.values()) { - for (String rootUrl : container.getUrls()) { - if (VfsUtilCore.isEqualOrAncestor(rootUrl, url)) { - return true; - } + if (VfsUtilCore.isUnder(url, Arrays.asList(container.getUrls()))) { + return true; } } return false; diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java index e290ebb70793..6dba855121cb 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java @@ -272,12 +272,8 @@ public class PatternCompiler { element.accept(new PsiRecursiveElementWalkingVisitor() { @Override - public void visitElement(PsiElement element) { - super.visitElement(element); - - if (!(element instanceof PsiErrorElement)) { - return; - } + public void visitErrorElement(PsiErrorElement element) { + super.visitErrorElement(element); final int startOffset = element.getTextRange().getStartOffset(); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java index 368240ff50be..f82ad12e5f4f 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java @@ -22,7 +22,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComponentWithBrowseButton; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -36,8 +35,6 @@ import com.intellij.structuralsearch.plugin.replace.ReplaceOptions; import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration; import com.intellij.ui.ComboboxWithBrowseButton; import com.intellij.ui.EditorTextField; -import com.intellij.ui.components.labels.LinkLabel; -import com.intellij.ui.components.labels.LinkListener; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -46,7 +43,6 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import javax.swing.text.BadLocationException; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -117,7 +113,7 @@ class EditVarConstraintsDialog extends DialogWrapper { withinCombo.getComboBox().setEditable(true); withinCombo.getButton().addActionListener(new ActionListener() { - public void actionPerformed(final ActionEvent e) { + public void actionPerformed(@NotNull final ActionEvent e) { final SelectTemplateDialog dialog = new SelectTemplateDialog(project, false, false); dialog.show(); if (dialog.getExitCode() == OK_EXIT_CODE) { @@ -191,7 +187,7 @@ class EditVarConstraintsDialog extends DialogWrapper { new ListSelectionListener() { boolean rollingBackSelection; - public void valueChanged(ListSelectionEvent e) { + public void valueChanged(@NotNull ListSelectionEvent e) { if (e.getValueIsAdjusting()) return; if (rollingBackSelection) { rollingBackSelection=false; @@ -212,7 +208,7 @@ class EditVarConstraintsDialog extends DialogWrapper { parameterList.setCellRenderer( new DefaultListCellRenderer() { - 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) { String name = ((Variable)value).getName(); if (Configuration.CONTEXT_VAR_NAME.equals(name)) name = SSRBundle.message("complete.match.variable.name"); if (isReplacementVariable(name)) { @@ -226,7 +222,7 @@ class EditVarConstraintsDialog extends DialogWrapper { maxoccursUnlimited.addChangeListener(new MyChangeListener(maxoccurs, true)); customScriptCode.getButton().addActionListener(new ActionListener() { - public void actionPerformed(final ActionEvent e) { + public void actionPerformed(@NotNull final ActionEvent e) { final EditScriptDialog dialog = new EditScriptDialog(project, customScriptCode.getChildComponent().getText()); dialog.show(); if (dialog.getExitCode() == OK_EXIT_CODE) { @@ -505,18 +501,7 @@ class EditVarConstraintsDialog extends DialogWrapper { formalArgType = createRegexComponent(); customScriptCode = new ComponentWithBrowseButton(createScriptComponent(), null); - myRegExHelpLabel = new LinkLabel(SSRBundle.message("regular.expression.help.label"), null, new LinkListener() { - public void linkSelected(LinkLabel aSource, Object aLinkData) { - try { - final JBPopup helpPopup = RegExHelpPopup.createRegExHelpPopup(); - helpPopup.showInCenterOf(mainForm); - } - catch (BadLocationException e) { - LOG.info(e); - } - } - }); - + myRegExHelpLabel = RegExHelpPopup.createRegExLink(SSRBundle.message("regular.expression.help.label"), regexp, LOG); myRegExHelpLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); } @@ -559,7 +544,7 @@ class EditVarConstraintsDialog extends DialogWrapper { inverted = _inverted; } - public void stateChanged(ChangeEvent e) { + public void stateChanged(@NotNull ChangeEvent e) { final JCheckBox jCheckBox = (JCheckBox)e.getSource(); component.setEnabled(inverted ^ jCheckBox.isSelected()); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java index 32f1302336f3..ecdccbe0e40b 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java @@ -1,6 +1,6 @@ package com.intellij.structuralsearch.plugin.ui; -import com.intellij.codeInsight.hint.TooltipGroup; +import com.intellij.codeInsight.hint.TooltipController; import com.intellij.codeInsight.template.impl.TemplateImplUtil; import com.intellij.codeInsight.template.impl.Variable; import com.intellij.openapi.editor.Document; @@ -11,7 +11,6 @@ import com.intellij.openapi.util.Key; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.Iterator; /** * Created by IntelliJ IDEA. @@ -21,7 +20,6 @@ import java.util.Iterator; * To change this template use File | Settings | File Templates. */ public class SubstitutionShortInfoHandler implements DocumentListener, EditorMouseMotionListener, CaretListener { - private static final TooltipGroup SS_INFO_TOOLTIP_GROUP = new TooltipGroup("SS_INFO_TOOLTIP_GROUP", 0); private long modificationTimeStamp; private final ArrayList variables = new ArrayList(); @@ -63,9 +61,7 @@ public class SubstitutionShortInfoHandler implements DocumentListener, EditorMou String varname = elements.subSequence(start + 1, end).toString(); Variable foundVar = null; - for(Iterator i=variables.iterator();i.hasNext();) { - final Variable var = i.next(); - + for (final Variable var : variables) { if (var.getName().equals(varname)) { foundVar = var; break; @@ -79,7 +75,10 @@ public class SubstitutionShortInfoHandler implements DocumentListener, EditorMou } if (text.length() > 0) { - UIUtil.showTooltip(editor, start, end, text, SS_INFO_TOOLTIP_GROUP); + UIUtil.showTooltip(editor, start, end + 1, text); + } + else { + TooltipController.getInstance().cancelTooltips(); } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java index aa3ca82725b0..1c0e40a9ba7e 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java @@ -26,6 +26,7 @@ import com.intellij.structuralsearch.plugin.StructuralReplaceAction; import com.intellij.structuralsearch.plugin.StructuralSearchAction; import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration; import com.intellij.structuralsearch.plugin.util.SmartPsiPointer; +import com.intellij.ui.HintHint; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,6 +42,7 @@ import java.awt.*; public class UIUtil { static Key LISTENER_KEY = Key.create("sslistener.key"); private static final String MODIFY_EDITOR_CONTENT = SSRBundle.message("modify.editor.content.command.name"); + private static final TooltipGroup SS_INFO_TOOLTIP_GROUP = new TooltipGroup("SS_INFO_TOOLTIP_GROUP", 0); @NonNls private static final String SS_GROUP = "structuralsearchgroup"; @NotNull @@ -212,22 +214,27 @@ public class UIUtil { } } - static void showTooltip(@NotNull Editor editor, final int start, int end, @NotNull String text, @NotNull TooltipGroup group) { - Rectangle visibleArea = editor.getScrollingModel().getVisibleArea(); - Point top = editor.logicalPositionToXY(editor.offsetToLogicalPosition(start)); + static void showTooltip(@NotNull Editor editor, final int start, int end, @NotNull String text) { + final Rectangle visibleArea = editor.getScrollingModel().getVisibleArea(); + final Point left = editor.logicalPositionToXY(editor.offsetToLogicalPosition(start)); final int documentLength = editor.getDocument().getTextLength(); if (end >= documentLength) end = documentLength; - Point bottom = editor.logicalPositionToXY(editor.offsetToLogicalPosition(end)); + final Point right = editor.logicalPositionToXY(editor.offsetToLogicalPosition(end)); - Point bestPoint = new Point(top.x, bottom.y + editor.getLineHeight()); + final Point bestPoint = new Point(left.x + (right.x - left.x) / 2, right.y + editor.getLineHeight() / 2); - if (!visibleArea.contains(bestPoint)) { - int defaultOffset = editor.logicalPositionToOffset(editor.xyToLogicalPosition(new Point(0, 0))); - bestPoint = editor.logicalPositionToXY(editor.offsetToLogicalPosition(defaultOffset)); + if (visibleArea.x > bestPoint.x) { + bestPoint.x = visibleArea.x; + } + else if (visibleArea.x + visibleArea.width < bestPoint.x) { + bestPoint.x = visibleArea.x + visibleArea.width - 5; } - Point p = SwingUtilities.convertPoint(editor.getContentComponent(), bestPoint, editor.getComponent().getRootPane().getLayeredPane()); - TooltipController.getInstance().showTooltip(editor, p, text, false, group); + final Point p = SwingUtilities.convertPoint(editor.getContentComponent(), bestPoint, + editor.getComponent().getRootPane().getLayeredPane()); + final HintHint hint = new HintHint(editor, bestPoint).setAwtTooltip(true).setHighlighterType(true) + .setCalloutShift(editor.getLineHeight() / 2 - 1); + TooltipController.getInstance().showTooltip(editor, p, text, visibleArea.width, false, SS_INFO_TOOLTIP_GROUP, hint); } public static void updateHighlighter(Editor editor, StructuralSearchProfile profile) { diff --git a/platform/testFramework/src/com/intellij/FileSetTestCase.java b/platform/testFramework/src/com/intellij/FileSetTestCase.java index ba2afa2f8d86..d89e175a52c2 100644 --- a/platform/testFramework/src/com/intellij/FileSetTestCase.java +++ b/platform/testFramework/src/com/intellij/FileSetTestCase.java @@ -16,6 +16,7 @@ import com.intellij.util.ArrayUtil; import junit.framework.TestSuite; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; @@ -80,6 +81,10 @@ public abstract class FileSetTestCase extends TestSuite { } } + protected String loadFile(File testFile) throws IOException { + return FileUtil.loadFile(testFile); + } + protected String getDelimiter() { return "---"; } @@ -116,7 +121,7 @@ public abstract class FileSetTestCase extends TestSuite { @Override protected void runTest() throws Throwable { - String content = FileUtil.loadFile(myTestFile); + String content = loadFile(myTestFile); assertNotNull(content); List input = new ArrayList(); diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java index b3557238124f..263c25b184b8 100644 --- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java +++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java @@ -270,6 +270,11 @@ public class MockChangeListManager extends ChangeListManagerEx { throw new UnsupportedOperationException(); } + @Override + public void addDirectoryToIgnoreImplicitly(@NotNull String path) { + throw new UnsupportedOperationException(); + } + @Override public void setFilesToIgnore(IgnoredFileBean... ignoredFiles) { throw new UnsupportedOperationException(); diff --git a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java index 930321fc61d5..71a1f50f1cd5 100644 --- a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java +++ b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java @@ -19,9 +19,7 @@ import com.intellij.injected.editor.DocumentWindow; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.lexer.Lexer; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.HighlighterColors; -import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; @@ -39,11 +37,13 @@ import com.intellij.psi.tree.IElementType; import com.intellij.reference.SoftReference; import com.intellij.usageView.UsageTreeColors; import com.intellij.usageView.UsageTreeColorsScheme; +import com.intellij.usages.impl.rules.UsageType; import com.intellij.util.Processor; import com.intellij.util.containers.FactoryMap; import com.intellij.util.text.CharArrayUtil; import com.intellij.util.text.StringFactory; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.lang.ref.WeakReference; @@ -234,7 +234,7 @@ public class ChunkExtractor { @NotNull final CharSequence chars, int hiStart, final int hiEnd, - @NotNull TextAttributesKey[] tokenHighlights, + @NotNull final TextAttributesKey[] tokenHighlights, final boolean selectUsageWithBold, @NotNull final List result) { final TextAttributes originalAttrs = convertAttributes(tokenHighlights); @@ -249,8 +249,12 @@ public class ChunkExtractor { int usageStart = segment.getStartOffset(); int usageEnd = segment.getEndOffset(); if (rangeIntersect(lastOffset[0], hiEnd, usageStart, usageEnd)) { - addChunk(chars, lastOffset[0], Math.max(lastOffset[0], usageStart), originalAttrs, false, result); - addChunk(chars, Math.max(lastOffset[0], usageStart), Math.min(hiEnd, usageEnd), originalAttrs, selectUsageWithBold, result); + addChunk(chars, lastOffset[0], Math.max(lastOffset[0], usageStart), originalAttrs, false, null, result); + + UsageType usageType = isHighlightedAsString(tokenHighlights) + ? UsageType.LITERAL_USAGE + : isHighlightedAsComment(tokenHighlights) ? UsageType.COMMENT_USAGE : null; + addChunk(chars, Math.max(lastOffset[0], usageStart), Math.min(hiEnd, usageEnd), originalAttrs, selectUsageWithBold, usageType, result); lastOffset[0] = usageEnd; if (usageEnd > hiEnd) { return false; @@ -260,22 +264,55 @@ public class ChunkExtractor { } }); if (lastOffset[0] < hiEnd) { - addChunk(chars, lastOffset[0], hiEnd, originalAttrs, false, result); + addChunk(chars, lastOffset[0], hiEnd, originalAttrs, false, null, result); } } + public static boolean isHighlightedAsComment(TextAttributesKey... keys) { + for (TextAttributesKey key : keys) { + if (key == DefaultLanguageHighlighterColors.DOC_COMMENT || + key == SyntaxHighlighterColors.DOC_COMMENT || + key == DefaultLanguageHighlighterColors.LINE_COMMENT || + key == SyntaxHighlighterColors.LINE_COMMENT || + key == DefaultLanguageHighlighterColors.BLOCK_COMMENT || + key == SyntaxHighlighterColors.JAVA_BLOCK_COMMENT + ) { + return true; + } + final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey(); + if (fallbackAttributeKey != null && isHighlightedAsComment(fallbackAttributeKey)) { + return true; + } + } + return false; + } + + public static boolean isHighlightedAsString(TextAttributesKey... keys) { + for (TextAttributesKey key : keys) { + if (key == DefaultLanguageHighlighterColors.STRING || key == SyntaxHighlighterColors.STRING) { + return true; + } + final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey(); + if (fallbackAttributeKey != null && isHighlightedAsString(fallbackAttributeKey)) { + return true; + } + } + return false; + } + private static void addChunk(@NotNull CharSequence chars, int start, int end, @NotNull TextAttributes originalAttrs, boolean bold, + @Nullable UsageType usageType, @NotNull List result) { if (start >= end) return; TextAttributes attrs = bold ? TextAttributes.merge(originalAttrs, new TextAttributes(null, null, null, null, Font.BOLD)) : originalAttrs; - result.add(new TextChunk(attrs, StringFactory.createShared(CharArrayUtil.fromSequence(chars, start, end)))); + result.add(new TextChunk(attrs, StringFactory.createShared(CharArrayUtil.fromSequence(chars, start, end)), usageType)); } private static boolean rangeIntersect(int s1, int e1, int s2, int e2) { diff --git a/platform/usageView/src/com/intellij/usages/TextChunk.java b/platform/usageView/src/com/intellij/usages/TextChunk.java index e1c3345d41da..e74debdb97fb 100644 --- a/platform/usageView/src/com/intellij/usages/TextChunk.java +++ b/platform/usageView/src/com/intellij/usages/TextChunk.java @@ -18,17 +18,25 @@ package com.intellij.usages; import com.intellij.openapi.editor.markup.AttributesFlyweight; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.usages.impl.rules.UsageType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class TextChunk { public static final TextChunk[] EMPTY_ARRAY = new TextChunk[0]; private final AttributesFlyweight myAttributes; private final String myText; + private final UsageType myType; public TextChunk(@NotNull TextAttributes attributes, @NotNull String text) { + this(attributes, text, null); + } + + public TextChunk(@NotNull TextAttributes attributes, @NotNull String text, @Nullable UsageType type) { myAttributes = attributes.getFlyweight(); myText = text; + myType = type; } @NotNull @@ -45,6 +53,10 @@ public class TextChunk { return getText(); } + public @Nullable UsageType getType() { + return myType; + } + @NotNull public SimpleTextAttributes getSimpleAttributesIgnoreBackground() { SimpleTextAttributes simples = SimpleTextAttributes.fromTextAttributes(getAttributes()); diff --git a/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java b/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java index aaccbfffbe18..d6c47e658df6 100644 --- a/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java +++ b/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java @@ -38,6 +38,7 @@ import com.intellij.reference.SoftReference; import com.intellij.ui.SimpleTextAttributes; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewBundle; +import com.intellij.usages.impl.rules.UsageType; import com.intellij.usages.rules.*; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; @@ -493,4 +494,15 @@ public class UsageInfo2UsageAdapter implements UsageInModule, public String getTooltipText() { return myUsageInfo.getTooltipText(); } + + public @Nullable UsageType getUsageType() { + TextChunk[] chunks = getText(); + for(TextChunk chunk:chunks) { + UsageType type = chunk.getType(); + if (type != null) { + return type; + } + } + return null; + } } diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java b/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java index b182bc31bceb..8d1de0bc06e3 100644 --- a/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java +++ b/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java @@ -19,6 +19,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.vcs.FileStatus; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.usages.*; import com.intellij.usages.rules.PsiElementUsage; @@ -42,7 +43,13 @@ public class UsageTypeGroupingRule implements UsageGroupingRuleEx { if (usage instanceof PsiElementUsage) { PsiElementUsage elementUsage = (PsiElementUsage)usage; - UsageType usageType = getUsageType(elementUsage.getElement(), targets); + PsiElement element = elementUsage.getElement(); + UsageType usageType = getUsageType(element, targets); + + if (usageType == null && element instanceof PsiFile && elementUsage instanceof UsageInfo2UsageAdapter) { + usageType = ((UsageInfo2UsageAdapter)elementUsage).getUsageType(); + } + if (usageType != null) return new UsageTypeGroup(usageType); if (usage instanceof ReadWriteAccessUsage) { diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java index b3c056ccfdda..be3f4f212072 100644 --- a/platform/util/src/com/intellij/icons/AllIcons.java +++ b/platform/util/src/com/intellij/icons/AllIcons.java @@ -74,6 +74,7 @@ public class AllIcons { public static final Icon Forward = IconLoader.getIcon("/actions/forward.png"); // 16x16 public static final Icon GC = IconLoader.getIcon("/actions/gc.png"); // 16x16 public static final Icon Get = IconLoader.getIcon("/actions/get.png"); // 16x16 + public static final Icon GroupByFile = IconLoader.getIcon("/actions/GroupByFile.png"); // 16x16 public static final Icon GroupByMethod = IconLoader.getIcon("/actions/groupByMethod.png"); // 16x16 public static final Icon GroupByModule = IconLoader.getIcon("/actions/GroupByModule.png"); // 16x16 public static final Icon GroupByModuleGroup = IconLoader.getIcon("/actions/GroupByModuleGroup.png"); // 16x16 diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java index 006276b42739..9834ef5b0d9e 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java @@ -134,6 +134,7 @@ public abstract class ChangeListManager implements ChangeListModification { public abstract List getRegisteredExecutors(); public abstract void addFilesToIgnore(final IgnoredFileBean... ignoredFiles); + public abstract void addDirectoryToIgnoreImplicitly(@NotNull String path); public abstract void setFilesToIgnore(final IgnoredFileBean... ignoredFiles); public abstract IgnoredFileBean[] getFilesToIgnore(); public abstract boolean isIgnoredFile(@NotNull VirtualFile file); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java index c3e20ed0e8bb..5e01feada2f3 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java @@ -23,15 +23,20 @@ import com.intellij.openapi.application.RuntimeInterruptedException; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.impl.DirectoryIndexExcludePolicy; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.conflicts.ChangelistConflictTracker; @@ -43,6 +48,7 @@ import com.intellij.openapi.vcs.readOnlyHandler.ReadonlyStatusHandlerImpl; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.EditorNotifications; import com.intellij.util.*; @@ -71,6 +77,7 @@ import java.util.concurrent.atomic.AtomicReference; public class ChangeListManagerImpl extends ChangeListManagerEx implements ProjectComponent, ChangeListOwner, JDOMExternalizable, RoamingTypeDisabled { public static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.ChangeListManagerImpl"); + private static final String EXCLUDED_CONVERTED_TO_IGNORED_OPTION = "EXCLUDED_CONVERTED_TO_IGNORED"; private final Project myProject; private final VcsConfiguration myConfig; @@ -102,6 +109,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec private final List myExecutors = new ArrayList(); private final IgnoredFilesComponent myIgnoredIdeaLevel; + private boolean myExcludedConvertedToIgnored; private ProgressIndicator myUpdateChangesProgressIndicator; public static final Topic LISTS_LOADED = new Topic( @@ -301,11 +309,29 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec myIgnoredIdeaLevel.add(IgnoredBeanFactory.ignoreFile(Project.DIRECTORY_STORE_FOLDER + "/workspace.xml", myProject)); } } + if (!Registry.is("ide.hide.excluded.files") && !myExcludedConvertedToIgnored) { + convertExcludedToIgnored(); + myExcludedConvertedToIgnored = true; + } } } }); } + void convertExcludedToIgnored() { + for (DirectoryIndexExcludePolicy policy : DirectoryIndexExcludePolicy.EP_NAME.getExtensions(myProject)) { + for (VirtualFile file : policy.getExcludeRootsForProject()) { + addDirectoryToIgnoreImplicitly(file.getPath()); + } + } + + for (Module module : ModuleManager.getInstance(myProject).getModules()) { + for (String url : ModuleRootManager.getInstance(module).getExcludeRootUrls()) { + addDirectoryToIgnoreImplicitly(VfsUtilCore.urlToPath(url)); + } + } + } + public void projectClosed() { ProjectLevelVcsManager.getInstance(myProject).removeVcsListener(myVcsListener); @@ -1272,6 +1298,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec setDefaultChangeList(myWorker.getListsCopy().get(0)); } } + myExcludedConvertedToIgnored = Boolean.parseBoolean(JDOMExternalizerUtil.readField(element, EXCLUDED_CONVERTED_TO_IGNORED_OPTION)); myConflictTracker.loadState(element); } } @@ -1285,6 +1312,9 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec worker = myWorker.copy(); } new ChangeListManagerSerialization(ignoredFilesComponent, worker).writeExternal(element); + if (myExcludedConvertedToIgnored) { + JDOMExternalizerUtil.writeField(element, EXCLUDED_CONVERTED_TO_IGNORED_OPTION, String.valueOf(true)); + } myConflictTracker.saveState(element); } } @@ -1352,6 +1382,15 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec scheduleUnversionedUpdate(); } + @Override + public void addDirectoryToIgnoreImplicitly(@NotNull String path) { + myIgnoredIdeaLevel.addIgnoredDirectoryImplicitly(path, myProject); + } + + public IgnoredFilesComponent getIgnoredFilesComponent() { + return myIgnoredIdeaLevel; + } + private void scheduleUnversionedUpdate() { final MyDirtyFilesScheduler scheduler = new MyDirtyFilesScheduler(myProject); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java index 311bcacd5bdb..0e20b4140b56 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java @@ -25,10 +25,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; +import java.util.*; class ChangeListManagerSerialization { @NonNls static final String ATT_ID = "id"; @@ -45,6 +42,8 @@ class ChangeListManagerSerialization { @NonNls static final String NODE_LIST = "list"; @NonNls static final String NODE_IGNORED = "ignored"; @NonNls static final String NODE_CHANGE = "change"; + @NonNls static final String MANUALLY_REMOVED_FROM_IGNORED = "manually-removed-from-ignored"; + @NonNls static final String DIRECTORY_TAG = "directory"; private final IgnoredFilesComponent myIgnoredIdeaLevel; private final ChangeListWorker myWorker; @@ -64,6 +63,14 @@ class ChangeListManagerSerialization { for (Element ignoredNode : ignoredNodes) { readFileToIgnore(ignoredNode); } + Element manuallyRemovedFromIgnoredTag = element.getChild(MANUALLY_REMOVED_FROM_IGNORED); + Set manuallyRemovedFromIgnoredPaths = new HashSet(); + if (manuallyRemovedFromIgnoredTag != null) { + for (Element tag : manuallyRemovedFromIgnoredTag.getChildren(DIRECTORY_TAG)) { + manuallyRemovedFromIgnoredPaths.add(tag.getAttributeValue(ATT_PATH)); + } + } + myIgnoredIdeaLevel.setDirectoriesManuallyRemovedFromIgnored(manuallyRemovedFromIgnoredPaths); } private void readChangeList(final Element listNode) { @@ -146,6 +153,14 @@ class ChangeListManagerSerialization { fileNode.setAttribute("mask", mask); } } + Set manuallyRemovedFromIgnored = myIgnoredIdeaLevel.getDirectoriesManuallyRemovedFromIgnored(); + if (!manuallyRemovedFromIgnored.isEmpty()) { + Element list = new Element(MANUALLY_REMOVED_FROM_IGNORED); + for (String path : manuallyRemovedFromIgnored) { + list.addContent(new Element(DIRECTORY_TAG).setAttribute(ATT_PATH, path)); + } + element.addContent(list); + } } private static class ChangeComparator implements Comparator { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java index 6d13d21a996c..f81c5069718b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java @@ -16,7 +16,10 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vcs.FileStatus; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.BeforeAfter; import java.util.List; @@ -30,13 +33,41 @@ public class FragmentedContent { private final Document myBefore; private final Document myAfter; private final List> myRanges; - private boolean myOneSide; - private boolean myIsAddition; - public FragmentedContent(Document before, Document after, List> ranges) { + private final boolean myOneSide; + private final boolean myIsAddition; + + private final VirtualFile myFileBefore; + private final VirtualFile myFileAfter; + private final FileType myFileTypeBefore; + private final FileType myFileTypeAfter; + + public FragmentedContent(Document before, Document after, List> ranges, Change change) { myBefore = before; myAfter = after; myRanges = ranges; + + final FileStatus fs = change.getFileStatus(); + myIsAddition = FileStatus.ADDED.equals(fs); + myOneSide = FileStatus.ADDED.equals(fs) || FileStatus.DELETED.equals(fs); + + if (change.getBeforeRevision() != null) { + myFileBefore = change.getBeforeRevision().getFile().getVirtualFile(); + myFileTypeBefore = change.getBeforeRevision().getFile().getFileType(); + } + else { + myFileBefore = null; + myFileTypeBefore = null; + } + + if (change.getAfterRevision() != null) { + myFileAfter = change.getAfterRevision().getFile().getVirtualFile(); + myFileTypeAfter = change.getAfterRevision().getFile().getFileType(); + } + else { + myFileAfter = null; + myFileTypeAfter = null; + } } public Document getBefore() { @@ -50,7 +81,7 @@ public class FragmentedContent { public List> getRanges() { return myRanges; } - + public int getSize() { return myRanges.size(); } @@ -59,15 +90,23 @@ public class FragmentedContent { return myOneSide; } - public void setOneSide(boolean oneSide) { - myOneSide = oneSide; - } - public boolean isAddition() { return myIsAddition; } - public void setIsAddition(boolean isAddition) { - myIsAddition = isAddition; + public VirtualFile getFileBefore() { + return myFileBefore; + } + + public VirtualFile getFileAfter() { + return myFileAfter; + } + + public FileType getFileTypeBefore() { + return myFileTypeBefore; + } + + public FileType getFileTypeAfter() { + return myFileTypeAfter; } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java index 2f3788ae509c..77dd9b3f42b3 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java @@ -81,10 +81,7 @@ public class FragmentedDiffRequestFromChange { } List> ranges = calculator.getRanges(); if (ranges == null || ranges.isEmpty()) return null; - FragmentedContent fragmentedContent = new FragmentedContent(calculator.getOldDocument(), calculator.getDocument(), ranges); - final FileStatus fs = change.getFileStatus(); - fragmentedContent.setIsAddition(FileStatus.ADDED.equals(fs)); - fragmentedContent.setOneSide(FileStatus.ADDED.equals(fs) || FileStatus.DELETED.equals(fs)); + FragmentedContent fragmentedContent = new FragmentedContent(calculator.getOldDocument(), calculator.getDocument(), ranges, change); VirtualFile file = filePath.getVirtualFile(); if (file == null) { filePath.hardRefresh(); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java index 87fe35d21922..b2eaa1f2e6e3 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java @@ -16,6 +16,7 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; @@ -27,6 +28,7 @@ import java.util.*; public class IgnoredFilesComponent { private final Set myFilesToIgnore; private final Map myFilesMap; + private final Set myDirectoriesManuallyRemovedFromIgnored; public IgnoredFilesComponent(final Project project, final boolean registerListener) { myFilesToIgnore = new LinkedHashSet(); @@ -40,11 +42,13 @@ public class IgnoredFilesComponent { } }); } + myDirectoriesManuallyRemovedFromIgnored = new HashSet(); } public IgnoredFilesComponent(final IgnoredFilesComponent other) { myFilesToIgnore = new LinkedHashSet(other.myFilesToIgnore); myFilesMap = new HashMap(other.myFilesMap); + myDirectoriesManuallyRemovedFromIgnored = new HashSet(other.myDirectoriesManuallyRemovedFromIgnored); } public void add(final IgnoredFileBean... filesToIgnore) { @@ -54,6 +58,37 @@ public class IgnoredFilesComponent { } } + public Set getDirectoriesManuallyRemovedFromIgnored() { + return Collections.unmodifiableSet(myDirectoriesManuallyRemovedFromIgnored); + } + + public void setDirectoriesManuallyRemovedFromIgnored(Set directories) { + myDirectoriesManuallyRemovedFromIgnored.clear(); + myDirectoriesManuallyRemovedFromIgnored.addAll(directories); + } + + public void addIgnoredDirectoryImplicitly(@NotNull String path, @NotNull Project project) { + synchronized (myFilesToIgnore) { + if (myDirectoriesManuallyRemovedFromIgnored.contains(path) || myDirectoriesManuallyRemovedFromIgnored.contains(path + "/")) { + return; + } + for (IgnoredFileBean bean : myFilesToIgnore) { + if (bean.getType() == IgnoreSettingsType.UNDER_DIR && FileUtil.isAncestor(bean.getPath(), path, false)) { + return; + } + } + List toRemove = new ArrayList(); + for (IgnoredFileBean bean : myFilesToIgnore) { + if ((bean.getType() == IgnoreSettingsType.UNDER_DIR || bean.getType() == IgnoreSettingsType.FILE) && + FileUtil.isAncestor(path, bean.getPath(), false)) { + toRemove.add(bean); + } + } + myFilesToIgnore.removeAll(toRemove); + myFilesToIgnore.add(IgnoredBeanFactory.ignoreUnderDirectory(path, project)); + } + } + private void addIgnoredFiles(final IgnoredFileBean... filesToIgnore) { for (IgnoredFileBean bean : filesToIgnore) { if (IgnoreSettingsType.FILE.equals(bean.getType())) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java index 2c2d0634b709..6e8a1a04d135 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java @@ -18,6 +18,8 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diff.DiffContent; import com.intellij.openapi.diff.SimpleContent; +import com.intellij.openapi.diff.impl.DiffHighlighterFactory; +import com.intellij.openapi.diff.impl.DiffHighlighterFactoryImpl; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.highlighter.*; @@ -35,6 +37,7 @@ import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsConfiguration; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.impl.ContentRevisionCache; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.BeforeAfter; import com.intellij.util.Consumer; @@ -140,6 +143,9 @@ public class PreparedFragmentedContent { fragmentedContent.getBefore(), fragmentedContent.getAfter()); // add "artificial" empty lines + final Document document = fragmentedContent.getBefore(); + final Document document1 = fragmentedContent.getAfter(); + // line starts BeforeAfter lines = new BeforeAfter(0, 0); for (BeforeAfter lineNumbers : expandedRanges) { @@ -155,7 +161,6 @@ public class PreparedFragmentedContent { oldConvertor.put(lines.getBefore(), lineNumbers.getBefore().getStartOffset()); newConvertor.put(lines.getAfter(), lineNumbers.getAfter().getStartOffset()); - final Document document = fragmentedContent.getBefore(); if (sbOld.length() > 0) { sbOld.append('\n'); } @@ -164,7 +169,6 @@ public class PreparedFragmentedContent { myBeforeFragments.add(beforeRange); sbOld.append(document.getText(beforeRange)); - final Document document1 = fragmentedContent.getAfter(); if (sbNew.length() > 0) { sbNew.append('\n'); } @@ -180,7 +184,23 @@ public class PreparedFragmentedContent { myLineRanges.add(new BeforeAfter(lines.getBefore() == 0 ? 0 : lines.getBefore() - 1, lines.getAfter() == 0 ? 0 : lines.getAfter() - 1)); - setHighlighters(fragmentedContent.getBefore(), fragmentedContent.getAfter(), expandedRanges); + if (!expandedRanges.isEmpty()) { + BeforeAfter last = expandedRanges.get(expandedRanges.size() - 1); + if (sbOld.length() > 0) { + if (document.getLineEndOffset(last.getBefore().getEndOffset()) != document.getTextLength()) { + sbOld.append('\n'); + oldConvertor.emptyLine(lines.getBefore()); + } + } + if (sbNew.length() > 0) { + if (document1.getLineEndOffset(last.getAfter().getEndOffset()) != document1.getTextLength()) { + sbNew.append('\n'); + newConvertor.emptyLine(lines.getAfter()); + } + } + } + + setHighlighters(fragmentedContent.getBefore(), fragmentedContent.getAfter(), expandedRanges, fragmentedContent); setTodoHighlighting(fragmentedContent.getBefore(), fragmentedContent.getAfter()); } }); @@ -323,29 +343,37 @@ public class PreparedFragmentedContent { } private void setHighlighters(final Document oldDocument, final Document document, - List> ranges) { - EditorHighlighterFactory editorHighlighterFactory = EditorHighlighterFactory.getInstance(); - final SyntaxHighlighter syntaxHighlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(myFileType, myProject, null); - final EditorHighlighter highlighter = - editorHighlighterFactory.createEditorHighlighter(syntaxHighlighter, EditorColorsManager.getInstance().getGlobalScheme()); - + List> ranges, FragmentedContent fragmentedContent) { + EditorHighlighter highlighter = createHighlighter(fragmentedContent.getFileTypeBefore(), + fragmentedContent.getFileBefore(), + fragmentedContent.getFileAfter(), myProject).createHighlighter(); highlighter.setEditor(new LightHighlighterClient(oldDocument, myProject)); highlighter.setText(oldDocument.getText()); HighlighterIterator iterator = highlighter.createIterator(ranges.get(0).getBefore().getStartOffset()); - FragmentedEditorHighlighter beforeHighlighter = - new FragmentedEditorHighlighter(iterator, getBeforeFragments(), 1, true); + FragmentedEditorHighlighter beforeHighlighter = new FragmentedEditorHighlighter(iterator, getBeforeFragments(), 1, true); setBeforeHighlighter(beforeHighlighter); - final EditorHighlighter highlighter1 = - editorHighlighterFactory.createEditorHighlighter(syntaxHighlighter, EditorColorsManager.getInstance().getGlobalScheme()); + EditorHighlighter highlighter1 = createHighlighter(fragmentedContent.getFileTypeAfter(), + fragmentedContent.getFileAfter(), + fragmentedContent.getFileBefore(), myProject).createHighlighter(); highlighter1.setEditor(new LightHighlighterClient(document, myProject)); highlighter1.setText(document.getText()); HighlighterIterator iterator1 = highlighter1.createIterator(ranges.get(0).getAfter().getStartOffset()); - FragmentedEditorHighlighter afterHighlighter = - new FragmentedEditorHighlighter(iterator1, getAfterFragments(), 1, true); + FragmentedEditorHighlighter afterHighlighter = new FragmentedEditorHighlighter(iterator1, getAfterFragments(), 1, true); setAfterHighlighter(afterHighlighter); } + private DiffHighlighterFactory createHighlighter(FileType contentType, + VirtualFile file, + VirtualFile otherFile, + Project project) { + VirtualFile baseFile = file; + if (baseFile == null) baseFile = otherFile; + if (contentType == null) contentType = myFileType; + + return new DiffHighlighterFactoryImpl(contentType, baseFile, project); + } + private void setTodoHighlighting(final Document oldDocument, final Document document) { final ContentRevisionCache cache = ProjectLevelVcsManager.getInstance(myProject).getContentRevisionCache(); final List> beforeTodoRanges = myBeforeNumber == null ? Collections.>emptyList() : diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java index 02586bba5e78..f70c84405c2d 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java @@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.DiffRequestFactory; import com.intellij.openapi.diff.MergeRequest; import com.intellij.openapi.diff.SimpleDiffRequest; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Getter; import com.intellij.openapi.util.io.FileUtil; @@ -60,6 +61,7 @@ public class ConflictedDiffRequestPresentable implements DiffRequestPresentable public MyResult step(DiffChainContext context) { if (myChange.getAfterRevision() == null) return createErrorResult(); final Getter mergeProvider = myChange.getMergeProvider(); + FileType type = myChange.getVirtualFile() != null ? myChange.getVirtualFile().getFileType() : null; if (mergeProvider != null) { // guaranteed text final MergeTexts texts = mergeProvider.get(); @@ -67,7 +69,7 @@ public class ConflictedDiffRequestPresentable implements DiffRequestPresentable return createErrorResult(); } final MergeRequest request = DiffRequestFactory.getInstance() - .create3WayDiffRequest(texts.getLeft(), texts.getRight(), texts.getBase(), myProject, null, null); + .create3WayDiffRequest(texts.getLeft(), texts.getRight(), texts.getBase(), type, myProject, null, null); request.setWindowTitle(FileUtil.toSystemDependentName(myFile.getPresentableUrl())); // todo titles? request.setVersionTitles(new String[] {myChange.getAfterRevision().getRevisionNumber().asString(), @@ -95,7 +97,8 @@ public class ConflictedDiffRequestPresentable implements DiffRequestPresentable final MergeRequest request = DiffRequestFactory.getInstance() .create3WayDiffRequest(CharsetToolkit.bytesToString(mergeData.CURRENT, charset), CharsetToolkit.bytesToString(mergeData.LAST, charset), - CharsetToolkit.bytesToString(mergeData.ORIGINAL, charset), myProject, null, null); + CharsetToolkit.bytesToString(mergeData.ORIGINAL, charset), + type, myProject, null, null); request.setWindowTitle(FileUtil.toSystemDependentName(myFile.getPresentableUrl())); // todo titles? VcsRevisionNumber lastRevisionNumber = mergeData.LAST_REVISION_NUMBER; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java index 6b4a3fb2c390..f7fbe4c9980d 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java @@ -325,7 +325,7 @@ public class ApplyPatchAction extends DumbAwareAction { MergeRequest request; if (myReadOnly) { request = DiffRequestFactory.getInstance() - .create3WayDiffRequest(leftText, rightText, originalContent, project, null, null); + .create3WayDiffRequest(leftText, rightText, originalContent, file.getFileType(), project, null, null); } else { request = DiffRequestFactory.getInstance().createMergeRequest(reverse ? rightText : leftText, reverse ? leftText : rightText, originalContent, diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java index 05b4e95b8672..a3ddc2ba450d 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java @@ -58,7 +58,10 @@ public class MergedDiffRequestPresentable implements DiffRequestPresentable { return new MyResult(badDiffRequest, DiffPresentationReturnValue.useRequest); } final MergeRequest request = DiffRequestFactory.getInstance() - .create3WayDiffRequest(revisionTexts.getLocal().toString(), revisionTexts.getPatched(), revisionTexts.getBase().toString(), myProject, null, null); + .create3WayDiffRequest(revisionTexts.getLocal().toString(), + revisionTexts.getPatched(), + revisionTexts.getBase().toString(), + filePath.getFileType(), myProject, null, null); request.setWindowTitle(VcsBundle.message("patch.apply.conflict.title", FileUtil.toSystemDependentName(myFile.getPresentableUrl()))); request.setVersionTitles(new String[] {"Current Version", "Base Version", FileUtil.toSystemDependentName(myAfterTitle)}); return new MyResult(request, DiffPresentationReturnValue.useRequest); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java index 82b676a8834d..6edfbb96c848 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java @@ -27,7 +27,8 @@ import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vcs.VcsBundle; -import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.ChangeListManagerImpl; +import com.intellij.openapi.vcs.changes.IgnoreSettingsType; import com.intellij.openapi.vcs.changes.IgnoredFileBean; import com.intellij.ui.*; import com.intellij.ui.components.JBList; @@ -37,13 +38,16 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; +import java.util.HashSet; +import java.util.Set; public class IgnoredSettingsPanel implements SearchableConfigurable, Configurable.NoScroll { private JBList myList; private JPanel myPanel; private final Project myProject; private DefaultListModel myModel; - private final ChangeListManager myChangeListManager; + private final ChangeListManagerImpl myChangeListManager; + private final Set myDirectoriesManuallyRemovedFromIgnored = new HashSet(); public IgnoredSettingsPanel(Project project) { myList = new JBList(); @@ -51,7 +55,7 @@ public class IgnoredSettingsPanel implements SearchableConfigurable, Configurabl myList.getEmptyText().setText(VcsBundle.message("no.ignored.files")); myProject = project; - myChangeListManager = ChangeListManager.getInstance(myProject); + myChangeListManager = ChangeListManagerImpl.getInstanceImpl(myProject); } private void setItems(final IgnoredFileBean[] filesToIgnore) { @@ -97,32 +101,30 @@ public class IgnoredSettingsPanel implements SearchableConfigurable, Configurabl } private void deleteItems() { - boolean contigiousSelection = true; - int minSelectionIndex = myList.getSelectionModel().getMinSelectionIndex(); - int maxSelectionIndex = myList.getSelectionModel().getMaxSelectionIndex(); - for (int i = minSelectionIndex; i <= maxSelectionIndex; i++) { - if (!myList.getSelectionModel().isSelectedIndex(i)) { - contigiousSelection = false; - break; - } - } - if (contigiousSelection) { - myModel.removeRange(minSelectionIndex, maxSelectionIndex); - } - else { - final Object[] selection = myList.getSelectedValues(); - for (Object item : selection) { - myModel.removeElement(item); + for (Object o : myList.getSelectedValues()) { + IgnoredFileBean bean = (IgnoredFileBean)o; + if (bean.getType() == IgnoreSettingsType.UNDER_DIR) { + myDirectoriesManuallyRemovedFromIgnored.add(bean.getPath()); } } + ListUtil.removeSelectedItems(myList); } public void reset() { setItems(myChangeListManager.getFilesToIgnore()); + myDirectoriesManuallyRemovedFromIgnored.clear(); + myDirectoriesManuallyRemovedFromIgnored.addAll(myChangeListManager.getIgnoredFilesComponent().getDirectoriesManuallyRemovedFromIgnored()); } public void apply() { - myChangeListManager.setFilesToIgnore(getItems()); + IgnoredFileBean[] toIgnore = getItems(); + myChangeListManager.setFilesToIgnore(toIgnore); + for (IgnoredFileBean bean : toIgnore) { + if (bean.getType() == IgnoreSettingsType.UNDER_DIR) { + myDirectoriesManuallyRemovedFromIgnored.remove(bean.getPath()); + } + } + myChangeListManager.getIgnoredFilesComponent().setDirectoriesManuallyRemovedFromIgnored(myDirectoriesManuallyRemovedFromIgnored); } public boolean isModified() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java index 37df433487ef..b230d4f72a0d 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java @@ -843,14 +843,21 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme @Override public Boolean compute() { return vf != null && (myExcludedIndex.isInContent(vf) || isFileInBaseDir(vf) || vf.equals(myProject.getBaseDir()) || - hasExplicitMapping(vf) || isInDirectoryBasedRoot(vf)) && !isIgnoredByVcs(vf); + hasExplicitMapping(vf) || isInDirectoryBasedRoot(vf) + || !Registry.is("ide.hide.excluded.files") && myExcludedIndex.isExcludedFile(vf)) + && !isIgnoredByVcs(vf); } }); } @Override public boolean isIgnoredByVcs(VirtualFile vf) { - return myExcludedIndex.isExcludedFile(vf); + if (Registry.is("ide.hide.excluded.files")) { + return myExcludedIndex.isExcludedFile(vf); + } + else { + return myExcludedIndex.isUnderIgnored(vf); + } } @Override diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java index 2769b3ca84cb..bb88f3dc3260 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java @@ -16,23 +16,21 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -/** - * @author Nadya Zabrodina - */ public class VcsRootErrorsFinder { - private final @NotNull Project myProject; - private final @NotNull ProjectLevelVcsManager myVcsManager; + @NotNull private final Project myProject; + @NotNull private final ProjectLevelVcsManager myVcsManager; + @NotNull private final VcsRootDetector myRootDetector; public VcsRootErrorsFinder(@NotNull Project project) { myProject = project; myVcsManager = ProjectLevelVcsManager.getInstance(project); + myRootDetector = ServiceManager.getService(myProject, VcsRootDetector.class); } @NotNull public Collection find() { List mappings = myVcsManager.getDirectoryMappings(); - Collection vcsRoots = ServiceManager.getService(myProject, VcsRootDetector.class).detect(); - + Collection vcsRoots = myRootDetector.detect(); Collection errors = new ArrayList(); errors.addAll(findExtraMappings(mappings)); errors.addAll(findUnregisteredRoots(mappings, vcsRoots)); diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java new file mode 100644 index 000000000000..4ec5ea4bcdad --- /dev/null +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java @@ -0,0 +1,94 @@ +package com.intellij.openapi.vcs.changes; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.CompilerProjectExtension; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PsiTestUtil; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nik + */ +public class ConvertExcludedToIgnoredTest extends PlatformTestCase { + private VirtualFile myContentRoot; + + @Override + public void setUp() throws Exception { + super.setUp(); + myContentRoot = getVirtualFile(createTempDirectory()); + PsiTestUtil.addContentRoot(myModule, myContentRoot); + } + + public void testExcludedFolder() throws IOException { + VirtualFile excluded = createChildDirectory(myContentRoot, "exc"); + PsiTestUtil.addExcludedRoot(myModule, excluded); + getChangeListManager().convertExcludedToIgnored(); + assertFalse(getChangeListManager().isIgnoredFile(myContentRoot)); + assertTrue(getChangeListManager().isIgnoredFile(excluded)); + assertIgnored(excluded); + } + + public void testModuleOutput() throws IOException { + VirtualFile output = createChildDirectory(myContentRoot, "out"); + PsiTestUtil.setCompilerOutputPath(myModule, output.getUrl(), false); + getChangeListManager().convertExcludedToIgnored(); + assertFalse(getChangeListManager().isIgnoredFile(myContentRoot)); + assertTrue(getChangeListManager().isIgnoredFile(output)); + assertIgnored(output); + } + + public void testProjectOutput() throws IOException { + VirtualFile output = getVirtualFile(createTempDir("projectOutput")); + CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(output.getUrl()); + getChangeListManager().convertExcludedToIgnored(); + assertTrue(getChangeListManager().isIgnoredFile(output)); + assertIgnored(output); + } + + public void testModuleOutputUnderProjectOutput() throws IOException { + VirtualFile output = getVirtualFile(createTempDir("projectOutput")); + CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(output.getUrl()); + VirtualFile moduleOutput = createChildDirectory(output, "module"); + PsiTestUtil.setCompilerOutputPath(myModule, moduleOutput.getUrl(), false); + getChangeListManager().convertExcludedToIgnored(); + assertTrue(getChangeListManager().isIgnoredFile(output)); + assertTrue(getChangeListManager().isIgnoredFile(moduleOutput)); + assertIgnored(output); + } + + public void testModuleOutputUnderExcluded() throws IOException { + VirtualFile excluded = createChildDirectory(myContentRoot, "target"); + PsiTestUtil.addExcludedRoot(myModule, excluded); + VirtualFile moduleOutput = createChildDirectory(excluded, "classes"); + PsiTestUtil.setCompilerOutputPath(myModule, moduleOutput.getUrl(), false); + getChangeListManager().convertExcludedToIgnored(); + assertTrue(getChangeListManager().isIgnoredFile(excluded)); + assertTrue(getChangeListManager().isIgnoredFile(moduleOutput)); + assertIgnored(excluded); + } + + private void assertIgnored(VirtualFile... ignoredDirs) { + assertIgnoredDirectories(getProject(), ignoredDirs); + } + + public static void assertIgnoredDirectories(final Project project, VirtualFile... ignoredDirs) { + List expectedIgnoredPaths = new ArrayList(); + for (VirtualFile dir : ignoredDirs) { + expectedIgnoredPaths.add(dir.getPath() + "/"); + } + List actualIgnoredPaths = new ArrayList(); + for (IgnoredFileBean fileBean : ChangeListManagerImpl.getInstanceImpl(project).getFilesToIgnore()) { + assertEquals("Unexpected ignore: " + fileBean, IgnoreSettingsType.UNDER_DIR, fileBean.getType()); + actualIgnoredPaths.add(fileBean.getPath()); + } + assertSameElements(expectedIgnoredPaths, actualIgnoredPaths); + } + + private ChangeListManagerImpl getChangeListManager() { + return ChangeListManagerImpl.getInstanceImpl(getProject()); + } +} diff --git a/platform/vcs-impl/vcs-impl.iml b/platform/vcs-impl/vcs-impl.iml index d5e517397bb9..9492e1b4205c 100644 --- a/platform/vcs-impl/vcs-impl.iml +++ b/platform/vcs-impl/vcs-impl.iml @@ -18,6 +18,7 @@ + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 3582822645d4..3fe8b70d1a8d 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -422,7 +422,7 @@ public class XDebugSessionImpl implements XDebugSession { } } - private boolean isBreakpointActive(final XBreakpoint b) { + public boolean isBreakpointActive(final XBreakpoint b) { return !areBreakpointsMuted() && b.isEnabled() && !myInactiveSlaveBreakpoints.contains(b); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form index 64239d330fd1..4ce06a6b52da 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form @@ -83,7 +83,7 @@ - + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java index b0b5998ef71f..994e51f2bbc4 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java @@ -62,6 +62,6 @@ public class XBreakpointFileGroupingRule extends XBreakpointGroupingRuleclass Y { void foo(String s) { new X() {{ - System.out.println(s); // problem indicated here - }} + System.out.println(s); // here the field is accessed not the parameter + }}; } } diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java index 99c6a2480928..a2b334c2661c 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java @@ -31,7 +31,7 @@ public class ExtendsConcreteCollectionInspectionTest extends LightInspectionTest protected String[] getEnvironmentClasses() { return new String[] { "package java.util;" + - "public class LinkedHashMap {" + + "public class LinkedHashMap extends HashMap implements Map{" + " protected boolean removeEldestEntry(Map.Entry eldest) {\n" + " return false;\n" + " }" + diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java index 6f55047feb2f..e3617711d6c0 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java @@ -92,6 +92,9 @@ public class ObjectsRequireNonNullIntention extends Intention { @Override public boolean satisfiedBy(PsiElement element) { + if (!PsiUtil.isLanguageLevel7OrHigher(element)) { + return false; + } if (!(element instanceof PsiReferenceExpression)) { return false; } diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 855deba56575..03e3b544b5ed 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -18,6 +18,7 @@ package org.jetbrains.jps.incremental.groovy; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -58,6 +59,8 @@ import org.jetbrains.jps.model.library.sdk.JpsSdk; import org.jetbrains.jps.service.JpsServiceManager; import org.jetbrains.jps.service.SharedThreadPool; import org.jetbrains.org.objectweb.asm.ClassReader; +import org.jetbrains.org.objectweb.asm.ClassVisitor; +import org.jetbrains.org.objectweb.asm.Opcodes; import java.io.File; import java.io.IOException; @@ -434,9 +437,14 @@ public class GroovyBuilder extends ModuleLevelBuilder { final String sourcePath = FileUtil.toSystemIndependentName(item.sourcePath); final String outputPath = FileUtil.toSystemIndependentName(item.outputPath); final File outputFile = new File(outputPath); - outputConsumer.registerOutputFile(target, outputFile, Collections.singleton(sourcePath)); + final File srcFile = new File(sourcePath); try { - callback.associate(outputPath, sourcePath, new ClassReader(FileUtil.loadFileBytes(outputFile))); + final byte[] bytes = FileUtil.loadFileBytes(outputFile); + outputConsumer.registerCompiledClass( + target, + new CompiledClass(outputFile, srcFile, readClassName(bytes), new BinaryContent(bytes)) + ); + callback.associate(outputPath, sourcePath, new ClassReader(bytes)); } catch (Throwable e) { // need this to make sure that unexpected errors in, for example, ASM will not ruin the compilation @@ -446,7 +454,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { myBuilderName, BuildMessage.Kind.WARNING, message + "\n" + CompilerMessage.getTextFromThrowable(e), sourcePath) ); } - successfullyCompiledFiles.add(new File(sourcePath)); + successfullyCompiledFiles.add(srcFile); } } } @@ -454,6 +462,16 @@ public class GroovyBuilder extends ModuleLevelBuilder { return JavaBuilderUtil.updateMappings(context, delta, dirtyFilesHolder, chunk, toCompile, successfullyCompiledFiles); } + private static String readClassName(byte[] classBytes) throws IOException{ + final Ref nameRef = Ref.create(null); + new ClassReader(classBytes).accept(new ClassVisitor(Opcodes.ASM5) { + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + nameRef.set(name.replace('/', '.')); + } + }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + return nameRef.get(); + } + private static Collection generateClasspath(CompileContext context, ModuleChunk chunk) { final Set cp = new LinkedHashSet(); //groovy_rt.jar diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GrFindManagerTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/GrFindManagerTest.java index 6112a2151a7e..c2a62a7b2a9c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GrFindManagerTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GrFindManagerTest.java @@ -44,8 +44,7 @@ public class GrFindManagerTest extends DaemonAnalyzerTestCase { public void testFindInLiteralToSkipQuotes() { FindModel findModel = FindManagerTestUtils.configureFindModel("^done$"); findModel.setRegularExpressions(true); - findModel.setInStringLiteralsOnly(true); - findModel.setInCommentsOnly(false); + findModel.setSearchContext(FindModel.SearchContext.IN_STRINGS); String text = "def n = \"\"\"done\"\"\"\n def n = /done/\n def n = \"done\"\n def n = \"done2\""; FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text, "groovy"); } @@ -53,7 +52,7 @@ public class GrFindManagerTest extends DaemonAnalyzerTestCase { public void testFindInShellCommentsOfGroovy() { FindModel findModel = FindManagerTestUtils.configureFindModel("done"); findModel.setWholeWordsOnly(true); - findModel.setInCommentsOnly(true); + findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS); String text = "#! done done done\n"; FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text, "groovy"); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy index 2b5933fb4d31..d6363fb560db 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy @@ -18,16 +18,28 @@ package org.jetbrains.plugins.groovy.compiler import com.intellij.compiler.CompilerConfiguration import com.intellij.compiler.CompilerConfigurationImpl +import com.intellij.execution.executors.DefaultRunExecutor +import com.intellij.execution.impl.DefaultJavaProgramRunner +import com.intellij.execution.process.ProcessAdapter +import com.intellij.execution.process.ProcessEvent +import com.intellij.execution.process.ProcessHandler +import com.intellij.execution.process.ProcessOutputTypes +import com.intellij.execution.runners.ProgramRunner import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.PathManager import com.intellij.openapi.compiler.CompilerMessage import com.intellij.openapi.compiler.CompilerMessageCategory import com.intellij.openapi.compiler.options.ExcludeEntryDescription import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration import com.intellij.openapi.module.Module import com.intellij.openapi.roots.ModuleRootModificationUtil +import com.intellij.openapi.util.Key +import com.intellij.openapi.util.Ref import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiFile +import com.intellij.testFramework.PsiTestUtil import com.intellij.testFramework.TestLoggerFactory +import org.jetbrains.annotations.NotNull import org.jetbrains.plugins.groovy.lang.psi.GroovyFile /** @@ -822,4 +834,35 @@ class AppTest { def messages = make() assert messages.find { it.message.contains("Cannot compile Groovy files: no Groovy library is defined for module 'dependent'") } } + + public void testGroovyOutputIsInstrumented() { + myFixture.addFileToProject("Bar.groovy", + "import org.jetbrains.annotations.NotNull; " + + "public class Bar {" + + "void xxx(@NotNull String param) { println param }\n" + + "static void main(String[] args) { new Bar().xxx(null) }"+ + "}" + ); + + File annotations = new File(PathManager.getJarPathForClass(NotNull.class)); + PsiTestUtil.addLibrary(myModule, "annotations", annotations.getParent(), annotations.getName()); + + assertEmpty(make()); + + final Ref exceptionFound = Ref.create(Boolean.FALSE); + ProcessHandler process = runProcess("Bar", myModule, DefaultRunExecutor.class, new ProcessAdapter() { + @Override + public void onTextAvailable(ProcessEvent event, Key outputType) { + if (ProcessOutputTypes.SYSTEM != outputType) { + if (!exceptionFound.get()) { + exceptionFound.set(event.getText().contains("java.lang.IllegalArgumentException: Argument for @NotNull parameter 'param' of Bar.xxx must not be null")); + } + } + } + }, ProgramRunner.PROGRAM_RUNNER_EP.findExtension(DefaultJavaProgramRunner.class)); + process.waitFor(); + + assertTrue(exceptionFound.get()); + } + } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java index 65e1b5ed2dce..e2a313ef30a9 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java @@ -19,12 +19,15 @@ import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.ModuleOrderEntryImpl; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFileManager; @@ -45,6 +48,7 @@ import org.jetbrains.jps.model.java.JpsJavaExtensionService; import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import java.io.File; +import java.util.Arrays; import java.util.Set; public class MavenRootModelAdapter { @@ -176,10 +180,7 @@ public class MavenRootModelAdapter { public boolean isAlreadyExcluded(File f) { String url = toUrl(f.getPath()).getUrl(); - for (String excludedUrl : myRootModel.getExcludeRootUrls()) { - if (VfsUtilCore.isEqualOrAncestor(excludedUrl, url)) return true; - } - return false; + return VfsUtilCore.isUnder(url, Arrays.asList(myRootModel.getExcludeRootUrls())); } private boolean exists(String path) { @@ -193,6 +194,10 @@ public class MavenRootModelAdapter { if (e == null) return; if (e.getUrl().equals(url.getUrl())) return; e.addExcludeFolder(url.getUrl()); + if (!Registry.is("ide.hide.excluded.files")) { + Project project = myRootModel.getProject(); + ChangeListManager.getInstance(project).addDirectoryToIgnoreImplicitly(toPath(path).getPath()); + } } public void unregisterAll(String path, boolean under, boolean unregisterSources) { diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java index e6e946e71c15..cea4ea2232e9 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java @@ -18,6 +18,8 @@ package org.jetbrains.idea.maven.project; import com.intellij.ProjectTopics; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.roots.*; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; import org.jetbrains.idea.maven.MavenImportingTestCase; @@ -49,6 +51,23 @@ public class MavenFoldersImporterTest extends MavenImportingTestCase { assertNull(myProjectRoot.findChild("target")); } + public void testIgnoreTargetFolder() throws Exception { + importProject("test" + + "project" + + "1"); + + new File(myProjectRoot.getPath(), "target/classes").mkdirs(); + updateProjectFolders(); + + assertExcludes("project", "target"); + myProjectRoot.refresh(false, true); + VirtualFile target = myProjectRoot.findChild("target"); + assertNotNull(target); + if (!Registry.is("ide.hide.excluded.files")) { + assertTrue(ChangeListManager.getInstance(myProject).isIgnoredFile(target)); + } + } + public void testUpdatingFoldersForAllTheProjects() throws Exception { createProjectPom("test" + "project" + diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java index b29fc4f78141..8f5084b87391 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java @@ -115,21 +115,18 @@ public class PropertiesImplUtil extends PropertiesUtil { @Nullable public static ResourceBundle createByUrl(final @NotNull String url, final @NotNull Project project) { - if (!url.startsWith(ResourceBundleImpl.RESOURCE_BUNDLE_PREFIX)) return null; - - final String defaultPropertiesUrl = url.substring(ResourceBundleImpl.RESOURCE_BUNDLE_PREFIX.length()); - final int idx = defaultPropertiesUrl.lastIndexOf('/'); + final int idx = url.lastIndexOf('/'); if (idx == -1) return null; - final String baseDirectoryName = defaultPropertiesUrl.substring(0, idx); - final String baseName = defaultPropertiesUrl.substring(idx + 1); + final String baseDirectoryName = url.substring(0, idx); + final String baseName = url.substring(idx + 1); final VirtualFile baseDirectoryVirtualFile = VirtualFileManager.getInstance().findFileByUrl(baseDirectoryName); if (baseDirectoryVirtualFile == null) { return null; } - final PsiFile baseDirectory = PsiManager.getInstance(project).findFile(baseDirectoryVirtualFile); - if (baseDirectory == null || !(baseDirectory instanceof PsiDirectory)) { + final PsiDirectory baseDirectory = PsiManager.getInstance(project).findDirectory(baseDirectoryVirtualFile); + if (baseDirectory == null) { return null; } - return getResourceBundle(baseName, (PsiDirectory)baseDirectory); + return getResourceBundle(baseName, baseDirectory); } } diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java index d257824166e9..ca5c8aa39a36 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java @@ -23,16 +23,13 @@ import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.util.SmartList; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.List; public class ResourceBundleImpl extends ResourceBundle { - @NonNls public static final String RESOURCE_BUNDLE_PREFIX = "resourceBundle:"; @NotNull private final PropertiesFile myDefaultPropertiesFile; public ResourceBundleImpl(@NotNull final PropertiesFile defaultPropertiesFile) { @@ -106,6 +103,6 @@ public class ResourceBundleImpl extends ResourceBundle { } public String getUrl() { - return RESOURCE_BUNDLE_PREFIX + getBaseDirectory() + "/" + getBaseName(); + return getBaseDirectory() + "/" + getBaseName(); } } \ No newline at end of file diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java index cb60de04bc4f..398b9ae1f8e4 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java @@ -23,11 +23,13 @@ import com.intellij.lang.properties.*; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.components.*; import com.intellij.openapi.project.Project; -import gnu.trove.THashMap; +import com.intellij.util.containers.HashMap; +import com.intellij.util.containers.SoftFactoryMap; +import com.intellij.util.xmlb.annotations.MapAnnotation; +import com.intellij.util.xmlb.annotations.Property; +import com.intellij.util.xmlb.annotations.Transient; import gnu.trove.TIntLongHashMap; import gnu.trove.TIntProcedure; -import org.jdom.Element; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,17 +43,22 @@ import java.util.Map; file = StoragePathMacros.PROJECT_FILE )} ) -public class PropertiesSeparatorManager implements PersistentStateComponent { - @NonNls private static final String FILE_ELEMENT = "file"; - @NonNls private static final String URL_ELEMENT = "url"; - @NonNls private static final String SEPARATOR_ATTR = "separator"; +public class PropertiesSeparatorManager implements PersistentStateComponent { private final Project myProject; public static PropertiesSeparatorManager getInstance(final Project project) { return ServiceManager.getService(project, PropertiesSeparatorManager.class); } - private final Map mySeparators = new THashMap(); + private PropertiesSeparatorManagerState myUserDefinedSeparators = new PropertiesSeparatorManagerState(); + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + private final SoftFactoryMap myGuessedSeparators = new SoftFactoryMap() { + @Nullable + @Override + protected String create(ResourceBundleImpl resourceBundle) { + return guessSeparator(resourceBundle); + } + }; public PropertiesSeparatorManager(final Project project) { myProject = project; @@ -62,12 +69,9 @@ public class PropertiesSeparatorManager implements PersistentStateComponent files = element.getChildren(FILE_ELEMENT); - for (Element fileElement : files) { - String url = fileElement.getAttributeValue(URL_ELEMENT, ""); - String separator = fileElement.getAttributeValue(SEPARATOR_ATTR,""); - separator = decodeSeparator(separator); - if (separator == null) { - continue; + public void loadState(final PropertiesSeparatorManagerState state) { + myUserDefinedSeparators = state.decode(myProject); + } + + @Nullable + @Override + public PropertiesSeparatorManagerState getState() { + return myUserDefinedSeparators.isEmpty() ? null : myUserDefinedSeparators.encode(); + } + + public static class PropertiesSeparatorManagerState { + @Property(surroundWithTag = false) + @MapAnnotation(surroundWithTag = false, + surroundKeyWithTag = false, + surroundValueWithTag = false, + keyAttributeName = "url", + valueAttributeName = "separator", + entryTagName = "file") + public Map mySeparators = new HashMap(); + + public Map getSeparators() { + return mySeparators; + } + + public boolean isEmpty() { + return mySeparators.isEmpty(); + } + + public PropertiesSeparatorManagerState encode() { + PropertiesSeparatorManagerState encodedState = new PropertiesSeparatorManagerState(); + for (final Map.Entry entry : mySeparators.entrySet()) { + String separator = entry.getValue(); + StringBuilder encoded = new StringBuilder(separator.length()); + for (int i=0;i entry : mySeparators.entrySet()) { + String separator = entry.getValue(); + separator = decodeSeparator(separator); + if (separator == null) { + continue; + } + final String url = entry.getKey(); + ResourceBundle resourceBundle = PropertiesImplUtil.createByUrl(url, project); + if (resourceBundle != null) { + decoded.getSeparators().put(url, separator); + } } + return decoded; } } @@ -140,42 +189,10 @@ public class PropertiesSeparatorManager implements PersistentStateComponent> 12, 16)); - encoded.append(Character.forDigit((c >> 8) & 0xf, 16)); - encoded.append(Character.forDigit((c >> 4) & 0xf, 16)); - encoded.append(Character.forDigit(c & 0xf, 16)); - } - Element fileElement = new Element(FILE_ELEMENT); - fileElement.setAttribute(URL_ELEMENT, url); - fileElement.setAttribute(SEPARATOR_ATTR, encoded.toString()); - element.addContent(fileElement); - } - return element; - } } diff --git a/python/helpers/pycharm/behave_runner.py b/python/helpers/pycharm/behave_runner.py index ca97659256cd..b11abfe7cc6b 100644 --- a/python/helpers/pycharm/behave_runner.py +++ b/python/helpers/pycharm/behave_runner.py @@ -220,11 +220,11 @@ if __name__ == "__main__": """ pass - tags = "" + tags = [] if len(sys.argv) > 1: for arg in filter(None, sys.argv[2::]): if str(arg).startswith("--tags"): - tags += " " + str(arg) + tags.append(str(arg)) else: raise Exception("Not a tag expression (should be --tags=..):{}".format(str(arg))) my_config = configuration.Configuration(command_args=tags) diff --git a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java index fa8881062ac3..808ec477e89a 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java +++ b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java @@ -25,6 +25,15 @@ import java.util.List; * @author vlan */ public interface StructuredDocString { + /** + * Creates parameter type documentation specific for certain doct type + * @param name param name + * @param type param type + * @return text to add to docsting + */ + @NotNull + String createParameterType(@NotNull String name, @NotNull String type); + String getDescription(); String getSummary(); diff --git a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java index 98f10f7abde1..36b70ec0f76a 100644 --- a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java +++ b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java @@ -76,12 +76,7 @@ public abstract class StructuredDocStringBase implements StructuredDocString { myDescription = builder.toString(); } - /** - * Creates parameter type documentation specific for certain doct type - * @param name param name - * @param type param type - * @return text to add to docsting - */ + @Override @NotNull public String createParameterType(@NotNull final String name, @NotNull final String type) { return myTagPrefix + TYPE + String.format(" %s %s", name, type); diff --git a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java index 4584f06ae8d9..6c86e72b1bcd 100644 --- a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java +++ b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java @@ -78,12 +78,12 @@ public abstract class PyInspectionVisitor extends PyElementVisitor { protected final void registerProblem(@Nullable final PsiElement element, @NotNull final String message, - @NotNull final LocalQuickFix quickFix) { + @NotNull final LocalQuickFix... quickFixes) { if (element == null || element.getTextLength() == 0) { return; } if (myHolder != null) { - myHolder.registerProblem(element, message, quickFix); + myHolder.registerProblem(element, message, quickFixes); } } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java index 0ae7ac1c7812..708e91743730 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java @@ -27,6 +27,7 @@ import com.jetbrains.python.psi.PyExpression; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +//TODO: Remove pydoc aswell public class PyRemoveArgumentQuickFix implements LocalQuickFix { @NotNull diff --git a/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java b/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java index ec6c806ffa1f..6d95604dc077 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java @@ -33,7 +33,9 @@ public class HtmlTextCompletionConfidence extends CompletionConfidence { if (node != null && node.getElementType() == XmlTokenType.XML_DATA_CHARACTERS) { PsiElement parent = contextElement.getParent(); if (parent instanceof XmlText || parent instanceof XmlDocument) { - String prefix = contextElement.getText().substring(0, offset - contextElement.getTextRange().getStartOffset()); + String contextElementText = contextElement.getText(); + int endOffset = offset - contextElement.getTextRange().getStartOffset(); + String prefix = contextElementText.substring(0, Math.min(contextElementText.length(), endOffset)); if (!StringUtil.startsWithChar(prefix, '<') && !StringUtil.startsWithChar(prefix, '&')) { return ThreeState.YES; } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java index ceb0d1dd61b9..421fbdd46564 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.template.emmet.filters; import com.intellij.codeInsight.template.emmet.nodes.GenerationNode; import com.intellij.codeInsight.template.emmet.tokens.TemplateToken; import com.intellij.lang.xml.XMLLanguage; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.psi.PsiElement; import com.intellij.psi.XmlElementVisitor; import com.intellij.psi.xml.XmlDocument; @@ -25,6 +26,7 @@ import com.intellij.psi.xml.XmlTag; import com.intellij.psi.xml.XmlTagValue; import org.jetbrains.annotations.NotNull; +import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -57,18 +59,27 @@ public class TrimZenCodingFilter extends ZenCodingFilter { if (document != null) { XmlTag tag = document.getRootTag(); if (tag != null && !tag.getText().isEmpty()) { - new XmlElementVisitor() { + tag.accept(new XmlElementVisitor() { @Override - public void visitXmlTag(XmlTag tag) { - if(!tag.isEmpty()) { - XmlTagValue tagValue = tag.getValue(); - tagValue.setText(PATTERN.matcher(tagValue.getText()).replaceAll("")); + public void visitXmlTag(final XmlTag tag) { + if (!tag.isEmpty()) { + final XmlTagValue tagValue = tag.getValue(); + final Matcher matcher = PATTERN.matcher(tagValue.getText()); + if (matcher.matches()) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + tagValue.setText(matcher.replaceAll("")); + } + }); + } } tag.acceptChildren(this); } - }.visitXmlTag(tag); + }); return tag.getText(); - } else { + } + else { return PATTERN.matcher(document.getText()).replaceAll(""); } } diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java index 86d2994c0e00..4f7f4efa5085 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java @@ -18,6 +18,7 @@ package com.intellij.ide.browsers; import com.intellij.concurrency.JobScheduler; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.util.ExecUtil; +import com.intellij.ide.GeneralSettings; import com.intellij.ide.IdeBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.ShowSettingsUtil; @@ -25,13 +26,29 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.AppUIUtil; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.net.URI; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; final class BrowserLauncherImpl extends BrowserLauncherAppless { + @Override + protected void browseUsingNotSystemDefaultBrowserPolicy(@NotNull URI uri, @NotNull GeneralSettings settings, @Nullable Project project) { + WebBrowserManager browserManager = WebBrowserManager.getInstance(); + if (browserManager.getDefaultBrowserPolicy() == DefaultBrowserPolicy.FIRST) { + WebBrowser browser = browserManager.getFirstActiveBrowser(); + if (browser != null) { + browseUsingPath(uri.toString(), null, browser, project, ArrayUtil.EMPTY_STRING_ARRAY); + return; + } + } + + super.browseUsingNotSystemDefaultBrowserPolicy(uri, settings, project); + } + @Override protected void doShowError(@Nullable final String error, @Nullable final WebBrowser browser, @Nullable final Project project, final String title, @Nullable final Runnable launchTask) { AppUIUtil.invokeOnEdt(new Runnable() { diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java index 3ae67def8424..af04e5896387 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java @@ -81,8 +81,8 @@ public class BrowserSelector { boolean hasFocus) { Icon baseIcon; if (value == null) { - WebBrowser defaultBrowser = WebBrowserManager.getInstance().getDefaultBrowser(); - baseIcon = defaultBrowser == null ? PlatformIcons.WEB_ICON : defaultBrowser.getIcon(); + WebBrowser firstBrowser = WebBrowserManager.getInstance().getFirstActiveBrowser(); + baseIcon = firstBrowser == null ? PlatformIcons.WEB_ICON : firstBrowser.getIcon(); } else { baseIcon = value.getIcon(); diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form index 52d074347bbc..23d7bf2ea873 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form @@ -22,7 +22,7 @@ - + diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java index 477d527ecbac..f43c0f6f4929 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java @@ -23,7 +23,6 @@ import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Comparing; -import com.intellij.ui.EnumComboBoxModel; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.TitledSeparator; import com.intellij.util.Function; @@ -34,6 +33,7 @@ import com.intellij.util.ui.LocalPathCellEditor; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.table.IconTableCellRenderer; import com.intellij.util.ui.table.TableModelEditor; +import org.jdesktop.swingx.combobox.ListComboBoxModel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,9 +46,9 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; +import java.util.ArrayList; import java.util.UUID; -import static com.intellij.ide.browsers.WebBrowserManager.DefaultBrowser; import static com.intellij.util.ui.table.TableModelEditor.EditableColumnInfo; final class BrowserSettingsPanel { @@ -73,7 +73,7 @@ final class BrowserSettingsPanel { } }; - private static final ColumnInfo[] COLUMNS = {new EditableColumnInfo() { + private static final EditableColumnInfo ACTIVE_COLUMN_INFO = new EditableColumnInfo() { @Override public Class getColumnClass() { return Boolean.class; @@ -88,44 +88,49 @@ final class BrowserSettingsPanel { public void setValue(ConfigurableWebBrowser item, Boolean value) { item.setActive(value); } - }, new EditableColumnInfo("Name") { - @Override - public String valueOf(ConfigurableWebBrowser item) { - return item.getName(); - } + }; - @Override - public void setValue(ConfigurableWebBrowser item, String value) { - item.setName(value); - } - }, new ColumnInfo("Family") { - @Override - public Class getColumnClass() { - return BrowserFamily.class; - } + private static final ColumnInfo[] COLUMNS = {ACTIVE_COLUMN_INFO, + new EditableColumnInfo("Name") { + @Override + public String valueOf(ConfigurableWebBrowser item) { + return item.getName(); + } - @Override - public BrowserFamily valueOf(ConfigurableWebBrowser item) { - return item.getFamily(); - } + @Override + public void setValue(ConfigurableWebBrowser item, String value) { + item.setName(value); + } + }, + new ColumnInfo("Family") { + @Override + public Class getColumnClass() { + return BrowserFamily.class; + } - @Override - public void setValue(ConfigurableWebBrowser item, BrowserFamily value) { - item.setFamily(value); - item.setSpecificSettings(value.createBrowserSpecificSettings()); - } + @Override + public BrowserFamily valueOf(ConfigurableWebBrowser item) { + return item.getFamily(); + } - @Nullable - @Override - public TableCellRenderer getRenderer(ConfigurableWebBrowser item) { - return IconTableCellRenderer.ICONABLE; - } + @Override + public void setValue(ConfigurableWebBrowser item, BrowserFamily value) { + item.setFamily(value); + item.setSpecificSettings(value.createBrowserSpecificSettings()); + } - @Override - public boolean isCellEditable(ConfigurableWebBrowser item) { - return !WebBrowserManager.getInstance().isPredefinedBrowser(item); - } - }, PATH_COLUMN_INFO}; + @Nullable + @Override + public TableCellRenderer getRenderer(ConfigurableWebBrowser item) { + return IconTableCellRenderer.ICONABLE; + } + + @Override + public boolean isCellEditable(ConfigurableWebBrowser item) { + return !WebBrowserManager.getInstance().isPredefinedBrowser(item); + } + }, + PATH_COLUMN_INFO}; private JPanel root; @@ -138,7 +143,7 @@ final class BrowserSettingsPanel { @SuppressWarnings("UnusedDeclaration") private JComponent browsersTable; - private ComboBox defaultBrowserComboBox; + private ComboBox defaultBrowserPolicyComboBox; private TableModelEditor browsersEditor; @@ -148,53 +153,55 @@ final class BrowserSettingsPanel { alternativeBrowserPathField.addBrowseFolderListener(IdeBundle.message("title.select.path.to.browser"), null, null, APP_FILE_CHOOSER_DESCRIPTOR); defaultBrowserPanel.setBorder(TitledSeparator.EMPTY_BORDER); - //noinspection unchecked - defaultBrowserComboBox.setModel(new EnumComboBoxModel(DefaultBrowser.class)); - if (BrowserLauncherAppless.canStartDefaultBrowser()) { - defaultBrowserComboBox.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - boolean customPathEnabled = e.getItem() == DefaultBrowser.ALTERNATIVE; - if (e.getStateChange() == ItemEvent.DESELECTED) { - if (customPathEnabled) { - customPathValue = alternativeBrowserPathField.getText(); - } - } - else if (e.getStateChange() == ItemEvent.SELECTED) { - alternativeBrowserPathField.setEnabled(customPathEnabled); - updateCustomPathTextFieldValue((DefaultBrowser)e.getItem()); - } - } - }); - - defaultBrowserComboBox.setRenderer(new ListCellRendererWrapper() { - @Override - public void customize(JList list, DefaultBrowser value, int index, boolean selected, boolean hasFocus) { - String name; - switch (value) { - case SYSTEM: - name = "System default"; - break; - case FIRST: - name = "First listed"; - break; - case ALTERNATIVE: - name = "Custom path"; - break; - default: - throw new IllegalStateException(); - } - - setText(name); - } - }); - - if (UIUtil.isUnderAquaLookAndFeel()) { - defaultBrowserComboBox.setBorder(new EmptyBorder(3, 0, 0, 0)); - } + ArrayList defaultBrowserPolicies = new ArrayList(); + if (BrowserLauncherAppless.canUseSystemDefaultBrowserPolicy()) { + defaultBrowserPolicies.add(DefaultBrowserPolicy.SYSTEM); } - else { - defaultBrowserComboBox.setVisible(false); + defaultBrowserPolicies.add(DefaultBrowserPolicy.FIRST); + defaultBrowserPolicies.add(DefaultBrowserPolicy.ALTERNATIVE); + + //noinspection Since15,unchecked + defaultBrowserPolicyComboBox.setModel(new ListComboBoxModel(defaultBrowserPolicies)); + defaultBrowserPolicyComboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean customPathEnabled = e.getItem() == DefaultBrowserPolicy.ALTERNATIVE; + if (e.getStateChange() == ItemEvent.DESELECTED) { + if (customPathEnabled) { + customPathValue = alternativeBrowserPathField.getText(); + } + } + else if (e.getStateChange() == ItemEvent.SELECTED) { + alternativeBrowserPathField.setEnabled(customPathEnabled); + updateCustomPathTextFieldValue((DefaultBrowserPolicy)e.getItem()); + } + } + }); + + defaultBrowserPolicyComboBox.setRenderer(new ListCellRendererWrapper() { + @Override + public void customize(JList list, DefaultBrowserPolicy value, int index, boolean selected, boolean hasFocus) { + String name; + switch (value) { + case SYSTEM: + name = "System default"; + break; + case FIRST: + name = "First listed"; + break; + case ALTERNATIVE: + name = "Custom path"; + break; + default: + throw new IllegalStateException(); + } + + setText(name); + } + }); + + if (UIUtil.isUnderAquaLookAndFeel()) { + defaultBrowserPolicyComboBox.setBorder(new EmptyBorder(3, 0, 0, 0)); } clearExtractedFiles.addActionListener(new ActionListener() { @@ -205,11 +212,11 @@ final class BrowserSettingsPanel { }); } - private void updateCustomPathTextFieldValue(DefaultBrowser browser) { - if (browser == DefaultBrowser.ALTERNATIVE) { + private void updateCustomPathTextFieldValue(@NotNull DefaultBrowserPolicy browser) { + if (browser == DefaultBrowserPolicy.ALTERNATIVE) { alternativeBrowserPathField.setText(customPathValue); } - else if (browser == DefaultBrowser.FIRST) { + else if (browser == DefaultBrowserPolicy.FIRST) { setCustomPathToFirstListed(); } else { @@ -272,18 +279,18 @@ final class BrowserSettingsPanel { .modelListener(new TableModelEditor.DataChangedListener() { @Override public void tableChanged(TableModelEvent event) { - update(event.getFirstRow()); + update(); } @Override public void dataChanged(@NotNull ColumnInfo columnInfo, int rowIndex) { - if (columnInfo == PATH_COLUMN_INFO) { - update(rowIndex); + if (columnInfo == PATH_COLUMN_INFO || columnInfo == ACTIVE_COLUMN_INFO) { + update(); } } - private void update(int rowIndex) { - if (rowIndex == 0 && getDefaultBrowser() == DefaultBrowser.FIRST) { + private void update() { + if (getDefaultBrowser() == DefaultBrowserPolicy.FIRST) { setCustomPathToFirstListed(); } } @@ -293,7 +300,15 @@ final class BrowserSettingsPanel { private void setCustomPathToFirstListed() { ListTableModel model = browsersEditor.getModel(); - alternativeBrowserPathField.setText(model.getRowCount() == 0 ? "" : model.getRowValue(0).getPath()); + for (int i = 0, n = model.getRowCount(); i < n; i++) { + ConfigurableWebBrowser browser = model.getRowValue(i); + if (browser.isActive() && browser.getPath() != null) { + alternativeBrowserPathField.setText(browser.getPath()); + return; + } + } + + alternativeBrowserPathField.setText(""); } @NotNull @@ -305,12 +320,12 @@ final class BrowserSettingsPanel { WebBrowserManager browserManager = WebBrowserManager.getInstance(); GeneralSettings generalSettings = GeneralSettings.getInstance(); - DefaultBrowser defaultBrowser = getDefaultBrowser(); - if (browserManager.getDefaultBrowserMode() != defaultBrowser || generalSettings.isConfirmExtractFiles() != confirmExtractFiles.isSelected()) { + DefaultBrowserPolicy defaultBrowserPolicy = getDefaultBrowser(); + if (browserManager.getDefaultBrowserPolicy() != defaultBrowserPolicy || generalSettings.isConfirmExtractFiles() != confirmExtractFiles.isSelected()) { return true; } - if (defaultBrowser == DefaultBrowser.ALTERNATIVE && + if (defaultBrowserPolicy == DefaultBrowserPolicy.ALTERNATIVE && !Comparing.strEqual(generalSettings.getBrowserPath(), alternativeBrowserPathField.getText())) { return true; } @@ -321,7 +336,7 @@ final class BrowserSettingsPanel { public void apply() { GeneralSettings settings = GeneralSettings.getInstance(); - settings.setUseDefaultBrowser(getDefaultBrowser() == DefaultBrowser.SYSTEM); + settings.setUseDefaultBrowser(getDefaultBrowser() == DefaultBrowserPolicy.SYSTEM); if (alternativeBrowserPathField.isEnabled()) { settings.setBrowserPath(alternativeBrowserPathField.getText()); @@ -330,26 +345,27 @@ final class BrowserSettingsPanel { settings.setConfirmExtractFiles(confirmExtractFiles.isSelected()); WebBrowserManager browserManager = WebBrowserManager.getInstance(); - browserManager.defaultBrowser = getDefaultBrowser(); + browserManager.defaultBrowserPolicy = getDefaultBrowser(); browserManager.setList(browsersEditor.apply()); } - private DefaultBrowser getDefaultBrowser() { - return (DefaultBrowser)defaultBrowserComboBox.getSelectedItem(); + private DefaultBrowserPolicy getDefaultBrowser() { + return (DefaultBrowserPolicy)defaultBrowserPolicyComboBox.getSelectedItem(); } public void reset() { + DefaultBrowserPolicy defaultBrowserPolicy = WebBrowserManager.getInstance().getDefaultBrowserPolicy(); + DefaultBrowserPolicy effectiveDefaultBrowserPolicy = defaultBrowserPolicy == DefaultBrowserPolicy.SYSTEM && !BrowserLauncherAppless.canUseSystemDefaultBrowserPolicy() + ? DefaultBrowserPolicy.ALTERNATIVE : defaultBrowserPolicy; + defaultBrowserPolicyComboBox.setSelectedItem(effectiveDefaultBrowserPolicy); + GeneralSettings settings = GeneralSettings.getInstance(); - - DefaultBrowser defaultBrowser = WebBrowserManager.getInstance().getDefaultBrowserMode(); - defaultBrowserComboBox.setSelectedItem(defaultBrowser); - confirmExtractFiles.setSelected(settings.isConfirmExtractFiles()); browsersEditor.reset(WebBrowserManager.getInstance().getList()); customPathValue = settings.getBrowserPath(); - alternativeBrowserPathField.setEnabled(defaultBrowser == DefaultBrowser.ALTERNATIVE); - updateCustomPathTextFieldValue(defaultBrowser); + alternativeBrowserPathField.setEnabled(effectiveDefaultBrowserPolicy == DefaultBrowserPolicy.ALTERNATIVE); + updateCustomPathTextFieldValue(effectiveDefaultBrowserPolicy); } public void selectBrowser(@NotNull WebBrowser browser) { diff --git a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java index 11502b5119a9..9f48b35905ae 100644 --- a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java +++ b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java @@ -56,7 +56,7 @@ final class ConfigurableWebBrowser extends WebBrowser { @Override public Icon getIcon() { if (family == BrowserFamily.CHROME) { - if (checkNameAndPath("Yandex")) { + if (WebBrowserManager.isYandexBrowser(this)) { return AllIcons.Xml.Browsers.Yandex16; } else if (checkNameAndPath("Dartium") || checkNameAndPath("Chromium")) { @@ -76,14 +76,7 @@ final class ConfigurableWebBrowser extends WebBrowser { } private boolean checkNameAndPath(@NotNull String what) { - if (StringUtil.containsIgnoreCase(name, what)) { - return true; - } - if (path != null) { - int index = path.lastIndexOf('/'); - return index > 0 ? path.indexOf(what, index + 1) != -1 : path.contains(what); - } - return false; + return WebBrowserManager.checkNameAndPath(what, this); } @Nullable diff --git a/java/jsp-openapi/src/com/intellij/psi/jsp/JspImplicitVariable.java b/xml/impl/src/com/intellij/ide/browsers/DefaultBrowserPolicy.java similarity index 54% rename from java/jsp-openapi/src/com/intellij/psi/jsp/JspImplicitVariable.java rename to xml/impl/src/com/intellij/ide/browsers/DefaultBrowserPolicy.java index 921cc8055dd1..4e1f0b2e0dc2 100644 --- a/java/jsp-openapi/src/com/intellij/psi/jsp/JspImplicitVariable.java +++ b/xml/impl/src/com/intellij/ide/browsers/DefaultBrowserPolicy.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. @@ -13,18 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.jsp; +package com.intellij.ide.browsers; -import com.intellij.pom.Navigatable; -import com.intellij.psi.ImplicitVariable; -import com.intellij.psi.PsiElement; -import com.intellij.navigation.NavigationItem; - -public interface JspImplicitVariable extends ImplicitVariable, NavigationItem { - JspImplicitVariable[] EMPTY_ARRAY = new JspImplicitVariable[0]; - int INSIDE = 1; - int AFTER = 2; - int getDeclarationRange(); - - PsiElement getDeclaration(); +public enum DefaultBrowserPolicy { + SYSTEM, FIRST, ALTERNATIVE } \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java index ce51ee07eebc..0b2ba6cb18c1 100644 --- a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java @@ -17,10 +17,7 @@ package com.intellij.ide.browsers; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Conditions; -import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.SimpleModificationTracker; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.SmartList; import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; @@ -36,53 +33,75 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers private static final Logger LOG = Logger.getInstance(WebBrowserManager.class); // default standard browser ID must be constant across all IDE versions on all machines for all users - private static final UUID DEFAULT_CHROME_ID = UUID.fromString("98CA6316-2F89-46D9-A9E5-FA9E2B0625B3"); + private static final UUID PREDEFINED_CHROME_ID = UUID.fromString("98CA6316-2F89-46D9-A9E5-FA9E2B0625B3"); // public, but only internal use - public static final UUID DEFAULT_FIREFOX_ID = UUID.fromString("A7BB68E0-33C0-4D6F-A81A-AAC1FDB870C8"); - private static final UUID DEFAULT_SAFARI_ID = UUID.fromString("E5120D43-2C3F-47EF-9F26-65E539E05186"); - private static final UUID DEFAULT_OPERA_ID = UUID.fromString("53E2F627-B1A7-4DFA-BFA7-5B83CC034776"); - private static final UUID DEFAULT_EXPLORER_ID = UUID.fromString("16BF23D4-93E0-4FFC-BFD6-CB13575177B0"); + public static final UUID PREDEFINED_FIREFOX_ID = UUID.fromString("A7BB68E0-33C0-4D6F-A81A-AAC1FDB870C8"); + private static final UUID PREDEFINED_SAFARI_ID = UUID.fromString("E5120D43-2C3F-47EF-9F26-65E539E05186"); + private static final UUID PREDEFINED_OPERA_ID = UUID.fromString("53E2F627-B1A7-4DFA-BFA7-5B83CC034776"); + private static final UUID PREDEFINED_YANDEX_ID = UUID.fromString("B1B2EC2C-20BD-4EE2-89C4-616DB004BCD4"); + private static final UUID PREDEFINED_EXPLORER_ID = UUID.fromString("16BF23D4-93E0-4FFC-BFD6-CB13575177B0"); + + private static final List PREDEFINED_BROWSERS = Arrays.asList( + new ConfigurableWebBrowser(PREDEFINED_CHROME_ID, BrowserFamily.CHROME), + new ConfigurableWebBrowser(PREDEFINED_FIREFOX_ID, BrowserFamily.FIREFOX), + new ConfigurableWebBrowser(PREDEFINED_SAFARI_ID, BrowserFamily.SAFARI), + new ConfigurableWebBrowser(PREDEFINED_OPERA_ID, BrowserFamily.OPERA), + new ConfigurableWebBrowser(PREDEFINED_YANDEX_ID, BrowserFamily.CHROME, "Yandex", SystemInfo.isWindows ? "browser" : (SystemInfo.isMac ? "Yandex" : "yandex"), false, BrowserFamily.CHROME.createBrowserSpecificSettings()), + new ConfigurableWebBrowser(PREDEFINED_EXPLORER_ID, BrowserFamily.EXPLORER) + ); private List browsers; - DefaultBrowser defaultBrowser = DefaultBrowser.SYSTEM; + DefaultBrowserPolicy defaultBrowserPolicy = DefaultBrowserPolicy.SYSTEM; public WebBrowserManager() { - browsers = new ArrayList(); - browsers.add(new ConfigurableWebBrowser(DEFAULT_CHROME_ID, BrowserFamily.CHROME)); - browsers.add(new ConfigurableWebBrowser(DEFAULT_FIREFOX_ID, BrowserFamily.FIREFOX)); - browsers.add(new ConfigurableWebBrowser(DEFAULT_SAFARI_ID, BrowserFamily.SAFARI)); - browsers.add(new ConfigurableWebBrowser(DEFAULT_OPERA_ID, BrowserFamily.OPERA)); - browsers.add(new ConfigurableWebBrowser(DEFAULT_EXPLORER_ID, BrowserFamily.EXPLORER)); + browsers = new ArrayList(PREDEFINED_BROWSERS); } public static WebBrowserManager getInstance() { return ServiceManager.getService(WebBrowserManager.class); } - boolean isPredefinedBrowser(@NotNull ConfigurableWebBrowser browser) { - UUID id = browser.getId(); - return id.equals(DEFAULT_CHROME_ID) || - id.equals(DEFAULT_FIREFOX_ID) || - id.equals(DEFAULT_SAFARI_ID) || - id.equals(DEFAULT_OPERA_ID) || - id.equals(DEFAULT_EXPLORER_ID); + public static boolean isYandexBrowser(@NotNull WebBrowser browser) { + return browser.getFamily().equals(BrowserFamily.CHROME) && (browser.getId().equals(PREDEFINED_YANDEX_ID) || checkNameAndPath("Yandex", browser)); } - public enum DefaultBrowser { - SYSTEM, FIRST, ALTERNATIVE + public static boolean isDartium(@NotNull WebBrowser browser) { + return browser.getFamily().equals(BrowserFamily.CHROME) && checkNameAndPath("Dartium", browser); + } + + static boolean checkNameAndPath(@NotNull String what, @NotNull WebBrowser browser) { + if (StringUtil.containsIgnoreCase(browser.getName(), what)) { + return true; + } + String path = browser.getPath(); + if (path != null) { + int index = path.lastIndexOf('/'); + return index > 0 ? path.indexOf(what, index + 1) != -1 : path.contains(what); + } + return false; + } + + boolean isPredefinedBrowser(@NotNull ConfigurableWebBrowser browser) { + UUID id = browser.getId(); + for (ConfigurableWebBrowser predefinedBrowser : PREDEFINED_BROWSERS) { + if (id.equals(predefinedBrowser.getId())) { + return true; + } + } + return false; } @NotNull - public DefaultBrowser getDefaultBrowserMode() { - return defaultBrowser; + public DefaultBrowserPolicy getDefaultBrowserPolicy() { + return defaultBrowserPolicy; } @Override public Element getState() { Element state = new Element("state"); - if (defaultBrowser != DefaultBrowser.SYSTEM) { - state.setAttribute("default", defaultBrowser.name().toLowerCase(Locale.ENGLISH)); + if (defaultBrowserPolicy != DefaultBrowserPolicy.SYSTEM) { + state.setAttribute("default", defaultBrowserPolicy.name().toLowerCase(Locale.ENGLISH)); } for (ConfigurableWebBrowser browser : browsers) { @@ -137,19 +156,19 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers UUID id; switch (family) { case CHROME: - id = DEFAULT_CHROME_ID; + id = PREDEFINED_CHROME_ID; break; case EXPLORER: - id = DEFAULT_EXPLORER_ID; + id = PREDEFINED_EXPLORER_ID; break; case FIREFOX: - id = DEFAULT_FIREFOX_ID; + id = PREDEFINED_FIREFOX_ID; break; case OPERA: - id = DEFAULT_OPERA_ID; + id = PREDEFINED_OPERA_ID; break; case SAFARI: - id = DEFAULT_SAFARI_ID; + id = PREDEFINED_SAFARI_ID; break; default: @@ -180,7 +199,7 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers String defaultValue = element.getAttributeValue("default"); if (!StringUtil.isEmpty(defaultValue)) { try { - defaultBrowser = DefaultBrowser.valueOf(defaultValue.toUpperCase(Locale.ENGLISH)); + defaultBrowserPolicy = DefaultBrowserPolicy.valueOf(defaultValue.toUpperCase(Locale.ENGLISH)); } catch (IllegalArgumentException e) { LOG.warn(e); @@ -225,6 +244,18 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers specificSettings)); } + // add removed/new predefined browsers + int n = list.size(); + pb: for (ConfigurableWebBrowser predefinedBrowser : PREDEFINED_BROWSERS) { + //noinspection ForLoopReplaceableByForEach + for (int i = 0; i < n; i++) { + if (list.get(i).getId().equals(predefinedBrowser.getId())) { + continue pb; + } + } + list.add(predefinedBrowser); + } + setList(list); } @@ -349,9 +380,9 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers } @Nullable - public WebBrowser getDefaultBrowser() { + public WebBrowser getFirstActiveBrowser() { for (ConfigurableWebBrowser browser : browsers) { - if (browser.isActive()) { + if (browser.isActive() && browser.getPath() != null) { return browser; } } diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java index 8ec2a2e55b67..e3bf3b5e6f6f 100644 --- a/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java +++ b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java @@ -151,7 +151,7 @@ public abstract class BaseOpenInBrowserAction extends DumbAwareAction { boolean applicable = false; WebBrowserUrlProvider provider = null; if (request != null) { - applicable = HtmlUtil.isHtmlFile(request.getFile()) && !(request.getVirtualFile() instanceof LightVirtualFile); + applicable = WebBrowserServiceImpl.isHtmlOrXmlFile(request.getFile()) && !(request.getVirtualFile() instanceof LightVirtualFile); if (!applicable) { provider = WebBrowserServiceImpl.getProvider(request); applicable = provider != null; diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java index 45cf021bbef8..1ead1b6faeb4 100644 --- a/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java +++ b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java @@ -16,10 +16,7 @@ package com.intellij.ide.browsers.actions; import com.intellij.ide.GeneralSettings; -import com.intellij.ide.browsers.OpenInBrowserRequest; -import com.intellij.ide.browsers.WebBrowser; -import com.intellij.ide.browsers.WebBrowserManager; -import com.intellij.ide.browsers.WebBrowserUrlProvider; +import com.intellij.ide.browsers.*; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; @@ -68,10 +65,11 @@ public class OpenFileInDefaultBrowserAction extends DumbAwareAction { @Nullable private static WebBrowser findUsingBrowser() { WebBrowserManager browserManager = WebBrowserManager.getInstance(); - if (browserManager.getDefaultBrowserMode() == WebBrowserManager.DefaultBrowser.FIRST) { - return browserManager.getDefaultBrowser(); + DefaultBrowserPolicy defaultBrowserPolicy = browserManager.getDefaultBrowserPolicy(); + if (defaultBrowserPolicy == DefaultBrowserPolicy.FIRST || (defaultBrowserPolicy == DefaultBrowserPolicy.SYSTEM && !BrowserLauncherAppless.canUseSystemDefaultBrowserPolicy())) { + return browserManager.getFirstActiveBrowser(); } - else if (browserManager.getDefaultBrowserMode() == WebBrowserManager.DefaultBrowser.ALTERNATIVE) { + else if (defaultBrowserPolicy == DefaultBrowserPolicy.ALTERNATIVE) { String path = GeneralSettings.getInstance().getBrowserPath(); if (!StringUtil.isEmpty(path)) { WebBrowser browser = browserManager.findBrowserById(path); diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java index 5cd056f869d9..3d0451d71b3d 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java @@ -18,6 +18,10 @@ package com.intellij.ide.browsers.impl; import com.intellij.ide.browsers.OpenInBrowserRequest; import com.intellij.ide.browsers.WebBrowserService; import com.intellij.ide.browsers.WebBrowserUrlProvider; +import com.intellij.lang.Language; +import com.intellij.lang.html.HTMLLanguage; +import com.intellij.lang.xhtml.XHTMLLanguage; +import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.impl.http.HttpVirtualFile; @@ -34,6 +38,11 @@ import java.util.Collection; import java.util.Collections; public class WebBrowserServiceImpl extends WebBrowserService { + public static boolean isHtmlOrXmlFile(@NotNull PsiElement element) { + Language language = element.getLanguage(); + return language == HTMLLanguage.INSTANCE || language == XHTMLLanguage.INSTANCE || language == XMLLanguage.INSTANCE; + } + @NotNull @Override public Collection getUrlsToOpen(@NotNull OpenInBrowserRequest request, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException { @@ -42,7 +51,7 @@ public class WebBrowserServiceImpl extends WebBrowserService { return Collections.singleton(Urls.newFromVirtualFile(virtualFile)); } - if (!preferLocalUrl || !HtmlUtil.isHtmlFile(request.getFile())) { + if (!preferLocalUrl || !isHtmlOrXmlFile(request.getFile())) { WebBrowserUrlProvider provider = getProvider(request); if (provider != null) { if (request.getResult() != null) {