summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2014-01-06 10:22:20 -0800
committerTor Norbye <tnorbye@google.com>2014-01-06 10:22:24 -0800
commitf2f7178ad6915927d918481b911e57a49785e4c4 (patch)
treec2b0f8906d38f5f1e2f5da853c67e09205816bf6 /platform
parent8668e1be0891658129cbc8f0965380f702c26755 (diff)
downloadidea-f2f7178ad6915927d918481b911e57a49785e4c4.tar.gz
Snapshot c11f3ac9bbde3f85d1f837ec3eb48a395ed7dd10 from idea/133.471 of git://git.jetbrains.org/idea/community.git
c11f3ac: faster xml properties indexing: don't process if no required namespace string present (cherry picked from commit 0845f9e) [r=Dmitry.Avdeev] 0be6c40: to get version sort copy of ClsStubBuilderFactory implementation array (cherry picked from commit c34b260) [r=Alexander.Podkhalusin] 8ed9df6: IDEA-116087 Warning when using new wrapper.gradleVersion construction (cherry picked from commit d3a81f0) d33b33a: Gradle: fix check for gradle-related files (cherry picked from commit 140b618) e8c50fa: Gradle: fix creation/sync of gradle wrapper files on project import 3fcf435: IDEA-99036 Changing breakpoint suspend policy from popup does not actually change the policy 033cdba: IDEA-116636 Android-Gradle facet is created when Gradle synchronization. related bug IDEA-116887 Gradle web artifacts do not contain compiled classes and JSP files (cherry picked from commit 64e7f51) 1f4d754: EA-52867 (null check) 3e2b5c5: proper processing of dom indices, 2 (cherry picked from commit e9d6759) 7061e85: proper processing of dom indices (cherry picked from commit e5401d6) e04883d: proper implementation and usage of indices for DOMStubs 5fa6cf9: do not load/try to index inner classes content / delegate to ClsStubBuilder for inner class identification (cherry picked from commit a085c19) [r=Alexander.Podkhalusin] 3a8fd3f: - use all BinaryStubBuilders versions in stable order to calculate stub version - introduce version for ClassStubBuilderFactory and use all class stub builder factories in stable order to calculate version of ClassFileStubBuilder [r=Eugene.Zhuravlev, Alexander.Podkhalusin] 57e7213: IDEA-118436 Resource Bundle Editor converts UTF8 characters to ASCII even in UTF8 file 1dc12b4: IDEA-112730 PhpStorm goes crazy with collapsed comments and soft wraps until crash eee52a9: IDEA-112730 PhpStorm goes crazy with collapsed comments and soft wraps until crash c187921: IDEA-112730 PhpStorm goes crazy with collapsed comments and soft wraps until crash 2119489: ActionTestCase extracted from CoffeeScript and Puppet (cherry picked from commit be905df) 12e8b76: Overriding language in VariableInplaceRenamer. (CoffeeScript) (cherry picked from commit b459118) c9069d1: IDEA-118587 IDEA may not exit with black window (cherry picked from commit a622b21) 6733c9e: WEB-9566 Debugger: optionally ignore certificate errors (cherry picked from commit af49f19) da588bc: move CertificatesManager to platform (cherry picked from commit 6dc50e6) f11ceb2: WEB-8262 Comment with line/block comment STILL doesn't work on HTML in ASP file (cherry picked from commit a83731c) [r=Rustam.Vyshnyakov] 8cfe207: WEB-849 "Comment with line comment" on empty line in <script> block generates HTML instead of JS comment (cherry picked from commit 73a14ec) [r=Rustam.Vyshnyakov] 36cf71c: WEB-6700 TODOs not recognized on multiple level language template (cherry picked from commit 9d00810) [r=Alexey.Gopachenko] 146d0c3: IDEA-118701 Multimodule project imported into IDEA via opening project file gets incorrect project name (cherry picked from commit 0912313) 25e5150: Bug fix: check not-null (cherry picked from commit 6b54183) 80932f6: IDEA-118601 New Module: Maven: click on "Create from archetype" reverts typed coordinates (cherry picked from commit d94c9a1) a419509: IDEA-116593 improve choosing of Android and Java SDKs when creating new android-gradle project/module: choose only Android SDK location (if we don't know it) on first step, not build target; choose Java SDK (if there is no any) separately, set it as project sdk and as internal jdk for newly created android sdk entities (cherry picked from commit 2bf19b4) e889183: Fixed IDEA-116006 Eclipse code style import: import the same xml does not pick up changes until manual synchronization (cherry picked from commit f6e9d9d) fd2b92e: licenses missing licenses for libraries used by android b5b25e5: Fixed IDEA-117788 Eclipse code style import: continuation indent is imported not multiplied to tab size (cherry picked from commit a9768ee) 074876e: remove all indexed state upon invalidateIndicesForFile (r=Eugene.Zhuravlev) caa4032: EA-35422 - IOOBE: EditorImpl.offsetToLogicalLine (from debugger) (cherry picked from commit c21cd02) [r=Peter.Gromov] b47b369: attach messages to root node if no running node found (cherry picked from commit 5c66005) 02cf0b4: [log] Flush & Close persistent enumerator on dispose() f84ff13: better way to instantiate PersistentHashMap 36d590f: [git] Wrap the VcsException not to loose the cause 339dede: [log] IDEA-115407 Disable graph-only-actions if there is no graph 3773e2c: [log] IDEA-115568 Don't crash if the log is empty cafe1a8: [log] IDEA-115901 Keep selection between refreshes and filtering 8169bbe: [log] rename type parameter to a more descriptive name 0548151: [log] remove pointless code 29f0909: [log] Don't use setFont(), instead supply value in getFont() 82f67f7: [log] IDEA-117816 small optimization in graph cell drawing 1acba78: IDEA-102942 Wrap always Chained methods calls over-format simple operations (cherry picked from commit 835ed38) 8ef13e9: IDEA-118613: catch all possible exceptions, that may be caused by corrupted storages 0654f14: IDEA-96131 Java: Braces placements don't work as expected for `Next Line` [CR-IC-3694] (cherry picked from commit 975cfe8) ee689af: WEB-10387 Mocha console log statements are not correctly aligned to their encasing tests (cherry picked from commit 6018640) b6b35e2: WEB-9517 Npm: Error loading package list (cherry picked from commit aa82d2a) 07d7344: test fix: explicit encoding is required 257ac80: cleanup 9b46832: IDEA-93034 SQL: MySQL: erasing the first backtick could erase the pair 6da1645: in case when some output and source roots intersect: do not stop rebuild if caches version is advanced (IDEA-118613) 631aea6: separate checks if compiler is enabled and compiler api is supported by compiler implementation 4ecc2a5: external build: added method to register output directory in source-to-output mapping instead of registering individual files to reduce occupied disk space (ZD-16651) [rev by Jeka] f344db7: don't copy ui-designer runtime classes to output if only NetBeans *.form files are found (ZD-14954) [rev by Jeka] 88de860: standalone JPS build: propagate 'forceBuild' option to dependencies implicitly included into compile scope [rev by Jeka] cbec9d7: [^Peter] EA-50899 - ISE: GrRegexImpl.createLiteralTextEscaper 3013e02: [^Peter] IDEA-117828 Groovy console: execute groovy code shortcut changed back 6ad8dbf: [^Peter] IDEA-117292 Groovy: checks for @Immutable class 8d2c8cf: EA-52292 fix (PHP template inside HTML comment case) (cherry picked from commit 41ccbd2) 1fc4a80: IDEA-118595 0f7f3a1: cleanup imports 09b3d12: style efdd1aa: OutputSuppressed option added for HgCommandExecutor, style changed, unnecessary parameters removed (cherry picked from commit 4d55fdd) 12789c5: cosmetics: revision hash template changed to long. (cherry picked from commit f1c78e1) 57c3348: Parents revision hash template changed to long. (cherry picked from commit 32ab1db) b70b45e: IDEA-118266 time measurements for all Mercurial commands added and log command debug output suppressed. (cherry picked from commit 75ec80e) f44f8d8: [^maxmedvedev] gdsl: be prepared to multithreaded scripts (cherry picked from commit a240a44) 6121316: + "trie" (cherry picked from commit 669ae41) 3c8884d: IDEA-118552 Generated ANT scripts do not honour cross-compile settings Change-Id: I18c031b09527bf8c7de6a529b546e66950a816d3
Diffstat (limited to 'platform')
-rw-r--r--platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java2
-rw-r--r--platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java14
-rw-r--r--platform/editor-ui-ex/src/com/intellij/psi/impl/search/IndexPatternSearcher.java11
-rw-r--r--platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java8
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java1
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java2
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java11
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java2
-rw-r--r--platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java2
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java18
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java27
-rw-r--r--platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java72
-rw-r--r--platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java5
-rw-r--r--platform/platform-api/src/com/intellij/util/net/CertificatesManager.java318
-rw-r--r--platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.form94
-rw-r--r--platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.java121
-rw-r--r--platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java19
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java4
-rw-r--r--platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java4
-rw-r--r--platform/platform-resources-en/src/misc/registry.properties1
-rw-r--r--platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java6
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java (renamed from platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java)4
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java102
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java29
-rw-r--r--platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java5
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/ActionTestCase.java100
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java43
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java19
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java10
-rw-r--r--platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java3
-rw-r--r--platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java14
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java2
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java26
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java48
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java4
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java8
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java27
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java12
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java8
41 files changed, 1091 insertions, 126 deletions
diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java
index 556db38f3b54..2661e6a6a069 100644
--- a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java
+++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java
@@ -163,7 +163,7 @@ public abstract class PlatformIdTableBuilding {
highlighter = editorHighlighter;
}
else {
- highlighter = HighlighterFactory.createHighlighter(null, myFile);
+ highlighter = HighlighterFactory.createHighlighter(inputData.getProject(), myFile);
highlighter.setText(chars);
}
diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java
index b9f8ec632b3c..dca89ac7bf8a 100644
--- a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java
+++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java
@@ -28,6 +28,7 @@ import com.intellij.psi.search.IndexPatternProvider;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.IntInlineKeyDescriptor;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NonNls;
@@ -82,15 +83,10 @@ public class TodoIndex extends FileBasedIndexExtension<TodoIndexEntry, Integer>
}
};
- private final DataExternalizer<Integer> myValueExternalizer = new DataExternalizer<Integer>() {
+ private final DataExternalizer<Integer> myValueExternalizer = new IntInlineKeyDescriptor() {
@Override
- public void save(final DataOutput out, final Integer value) throws IOException {
- out.writeInt(value.intValue());
- }
-
- @Override
- public Integer read(final DataInput in) throws IOException {
- return Integer.valueOf(in.readInt());
+ protected boolean isCompactFormat() {
+ return true;
}
};
@@ -131,7 +127,7 @@ public class TodoIndex extends FileBasedIndexExtension<TodoIndexEntry, Integer>
@Override
public int getVersion() {
- return 5;
+ return 6;
}
@Override
diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/search/IndexPatternSearcher.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/search/IndexPatternSearcher.java
index d108c6030e6c..adc24b1a1c95 100644
--- a/platform/editor-ui-ex/src/com/intellij/psi/impl/search/IndexPatternSearcher.java
+++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/search/IndexPatternSearcher.java
@@ -29,6 +29,7 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.psi.impl.cache.CacheUtil;
import com.intellij.psi.impl.cache.TodoCacheManager;
import com.intellij.psi.search.IndexPattern;
import com.intellij.psi.search.IndexPatternOccurrence;
@@ -187,15 +188,7 @@ public class IndexPatternSearcher implements QueryExecutor<IndexPatternOccurrenc
if (lexer.getTokenStart() >= range.getEndOffset()) break;
}
- boolean isComment = commentTokens.contains(tokenType);
- if (!isComment) {
- final Language commentLang = tokenType.getLanguage();
- final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(commentLang);
- if (parserDefinition != null) {
- final TokenSet langCommentTokens = parserDefinition.getCommentTokens();
- isComment = langCommentTokens.contains(tokenType);
- }
- }
+ boolean isComment = commentTokens.contains(tokenType) || CacheUtil.isInComments(tokenType);
if (isComment) {
final int startDelta = builderForFile != null ? builderForFile.getCommentStartDelta(lexer.getTokenType()) : 0;
diff --git a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java
index 978a6c80c9e4..27f7d10b1646 100644
--- a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java
+++ b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java
@@ -37,6 +37,7 @@ public abstract class StubProcessingHelperBase {
PsiFile _psifile = PsiManager.getInstance(project).findFile(file);
PsiFileWithStubSupport psiFile = null;
+ boolean customStubs = false;
if (_psifile != null && !(_psifile instanceof PsiPlainTextFile)) {
_psifile = _psifile.getViewProvider().getStubBindingRoot();
@@ -44,7 +45,9 @@ public abstract class StubProcessingHelperBase {
psiFile = (PsiFileWithStubSupport)_psifile;
stubTree = psiFile.getStubTree();
if (stubTree == null && psiFile instanceof PsiFileImpl) {
- stubTree = ((PsiFileImpl)psiFile).calcStubTree();
+ BinaryFileStubBuilder stubBuilder = BinaryFileStubBuilders.INSTANCE.forFileType(psiFile.getFileType());
+ if (stubBuilder == null) stubTree = ((PsiFileImpl)psiFile).calcStubTree();
+ else customStubs = true;
}
}
}
@@ -57,6 +60,9 @@ public abstract class StubProcessingHelperBase {
if (objectStubTree == null) {
return true;
}
+ if (customStubs && !(objectStubTree instanceof StubTree)) {
+ return processor.process((Psi)psiFile); // e.g. dom indices
+ }
stubTree = (StubTree)objectStubTree;
final List<StubElement<?>> plained = stubTree.getPlainList();
for (int i = 0, size = value.size(); i < size; i++) {
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java
index bd324f7d7246..071330cc4d80 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java
@@ -217,6 +217,7 @@ public class ManageCodeStyleSchemesDialog extends DialogWrapper {
VirtualFile[] selection = fileChooser.choose(CodeStyleSchemesUIConfiguration.Util.getRecentImportFile(), null);
if (selection.length == 1) {
VirtualFile selectedFile = selection[0];
+ selectedFile.refresh(false, false);
CodeStyleSchemesUIConfiguration.Util.setRecentImportFile(selectedFile);
try {
InputStream nameInputStream = selectedFile.getInputStream();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java
index c4379e2f223b..6017a40b4a9b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java
@@ -129,7 +129,7 @@ public class BackspaceHandler extends EditorWriteActionHandler {
editor.getDocument().deleteString(offset, offset + 1);
}
- else if (c == '"' || c == '\''){
+ else if (c == '"' || c == '\'' || c == '`'){
char c1 = chars.charAt(offset);
if (c1 != c) return true;
if (wasClosingQuote) return true;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java
index b6c0f77f1a9f..75ae804182d5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java
@@ -213,8 +213,15 @@ public class CommentByLineCommentHandler implements CodeInsightActionHandler {
int offset = myDocument.getLineStartOffset(myStartLine);
offset = CharArrayUtil.shiftForward(myDocument.getCharsSequence(), offset, " \t");
- final Language languageSuitableForCompleteFragment = PsiUtilBase.reallyEvaluateLanguageInRange(offset, CharArrayUtil.shiftBackward(
- myDocument.getCharsSequence(), myDocument.getLineEndOffset(myEndLine), " \t\n"), myFile);
+ int endOffset = CharArrayUtil.shiftBackward(myDocument.getCharsSequence(), myDocument.getLineEndOffset(myEndLine), " \t\n");
+ final Language languageSuitableForCompleteFragment;
+ if (offset >= endOffset) { // we are on empty line
+ PsiElement element = myFile.findElementAt(offset);
+ if (element != null) languageSuitableForCompleteFragment = element.getParent().getLanguage();
+ else languageSuitableForCompleteFragment = null;
+ } else {
+ languageSuitableForCompleteFragment = PsiUtilBase.reallyEvaluateLanguageInRange(offset, endOffset, myFile);
+ }
Commenter blockSuitableCommenter =
languageSuitableForCompleteFragment == null ? LanguageCommenters.INSTANCE.forLanguage(myFile.getLanguage()) : null;
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
index 55d8c3940017..818ab3cb2126 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
@@ -246,7 +246,7 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
public static AnAction createConsoleExecAction(final LanguageConsoleImpl languageConsole,
final ProcessHandler processHandler,
final ConsoleExecuteActionHandler consoleExecuteActionHandler) {
- return new ConsoleExecuteAction(languageConsole, consoleExecuteActionHandler, ConsoleExecuteAction.CONSOLE_EXECUTE_ACTION_ID,
+ return new ConsoleExecuteAction(languageConsole, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(),
new LanguageConsoleBuilder.ProcessBackedExecutionEnabledCondition(processHandler));
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java
index adbc722f6d10..376561535a1e 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java
@@ -62,7 +62,7 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
);
private ResolveSnapshotProvider.ResolveSnapshot mySnapshot;
private TextRange mySelectedRange;
- private Language myLanguage;
+ protected Language myLanguage;
public VariableInplaceRenamer(@NotNull PsiNamedElement elementToRename, Editor editor) {
this(elementToRename, editor, elementToRename.getProject());
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
index 6f803ce35d66..cfadaeedc1dc 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -1775,7 +1775,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
// important: no hard referencing currentFC to avoid OOME, the methods introduced for this purpose!
final Computable<Boolean> update = index.update(inputId, currentFC);
- final FileType fileType = file.getFileType();
scheduleUpdate(indexId,
createUpdateComputableWithBufferingDisabled(update),
@@ -1972,7 +1971,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
if (!fileIsDirectory && !isTooLarge(file)) {
final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file);
//noinspection ForLoopReplaceableByForEach
- FileType fileType = file.getFileType();
boolean scheduleForUpdate = false;
boolean resetStamp = false;
@@ -2039,7 +2037,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
cleanProcessedFlag(file);
IndexingStamp.flushCache(file);
- final List<ID<?, ?>> affectedIndexCandidates = getAffectedIndexCandidates(file);
+ final List<ID<?, ?>> affectedIndexCandidates = IndexingStamp.getIndexedIds(file);
final List<ID<?, ?>> affectedIndices = new ArrayList<ID<?, ?>>(affectedIndexCandidates.size());
//noinspection ForLoopReplaceableByForEach
@@ -2047,14 +2045,10 @@ public class FileBasedIndexImpl extends FileBasedIndex {
final ID<?, ?> indexId = affectedIndexCandidates.get(i);
try {
if (!needsFileContentLoading(indexId)) {
- if (shouldUpdateIndex(file, indexId)) {
- updateSingleIndex(indexId, file, null);
- }
+ updateSingleIndex(indexId, file, null);
}
else { // the index requires file content
- if (shouldUpdateIndex(file, indexId)) {
- affectedIndices.add(indexId);
- }
+ affectedIndices.add(indexId);
}
}
catch (StorageException e) {
@@ -2069,7 +2063,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
- FileType fileType = file.getFileType();
for (ID<?, ?> indexId : affectedIndices) {
IndexingStamp.update(file, indexId, IndexInfrastructure.INVALID_STAMP2);
}
@@ -2408,11 +2401,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
}
- private boolean shouldUpdateIndex(final VirtualFile file, final ID<?, ?> indexId) {
- return getInputFilter(indexId).acceptInput(file) &&
- (isMock(file) || isFileIndexed(file, indexId));
- }
-
private boolean shouldIndexFile(final VirtualFile file, final ID<?, ?> indexId) {
return getInputFilter(indexId).acceptInput(file) &&
(isMock(file) || !isFileIndexed(file, indexId));
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
index 8531bcf688eb..35a304ef77e5 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
@@ -18,18 +18,21 @@ package com.intellij.util.indexing;
import com.intellij.openapi.vfs.InvalidVirtualFileAccessException;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.openapi.vfs.newvfs.FileAttribute;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
+import com.intellij.util.SmartList;
import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.io.DataInputOutputUtil;
import gnu.trove.TObjectLongHashMap;
import gnu.trove.TObjectLongProcedure;
+import gnu.trove.TObjectProcedure;
import org.jetbrains.annotations.Nullable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.util.List;
+import java.util.Collections;
import java.util.concurrent.ArrayBlockingQueue;
/**
@@ -178,6 +181,28 @@ public class IndexingStamp {
}
}
+ public static List<ID<?,?>> getIndexedIds(final VirtualFile file) {
+ synchronized (getStripedLock(file)) {
+ try {
+ Timestamps stamp = createOrGetTimeStamp(file);
+ if (stamp != null && stamp.myIndexStamps != null && !stamp.myIndexStamps.isEmpty()) {
+ final SmartList<ID<?, ?>> retained = new SmartList<ID<?, ?>>();
+ stamp.myIndexStamps.forEach(new TObjectProcedure<ID<?, ?>>() {
+ @Override
+ public boolean execute(ID<?, ?> object) {
+ retained.add(object);
+ return true;
+ }
+ });
+ return retained;
+ }
+ }
+ catch (InvalidVirtualFileAccessException ignored /*ok to ignore it here*/) {
+ }
+ }
+ return Collections.emptyList();
+ }
+
public static void flushCaches() {
flushCache(null);
myTimestampsCache.clear();
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java b/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java
index bfa99455c1a0..b18187610774 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java
@@ -33,6 +33,7 @@ import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
public class InstalledPackagesPanel extends JPanel {
protected final JButton myInstallButton;
@@ -397,8 +398,11 @@ public class InstalledPackagesPanel extends JPanel {
final Collection<InstalledPackage> finalPackages = packages;
final Map<String, RepoPackage> cache = buildNameToPackageMap(packageManagementService.getAllPackagesCached());
+ final boolean shouldFetchLatestVersionsForOnlyInstalledPackages = shouldFetchLatestVersionsForOnlyInstalledPackages();
if (cache.isEmpty()) {
- refreshLatestVersions();
+ if (!shouldFetchLatestVersionsForOnlyInstalledPackages) {
+ refreshLatestVersions();
+ }
}
application.invokeLater(new Runnable() {
@Override
@@ -414,6 +418,9 @@ public class InstalledPackagesPanel extends JPanel {
if (!cache.isEmpty()) {
myPackagesTable.setPaintBusy(false);
}
+ if (shouldFetchLatestVersionsForOnlyInstalledPackages) {
+ setLatestVersionsForInstalledPackages();
+ }
}
}
}, ModalityState.any());
@@ -423,6 +430,69 @@ public class InstalledPackagesPanel extends JPanel {
});
}
+ private InstalledPackage getInstalledPackageAt(int index) {
+ return (InstalledPackage) myPackagesTableModel.getValueAt(index, 0);
+ }
+
+ private void setLatestVersionsForInstalledPackages() {
+ final PackageManagementServiceEx serviceEx = getServiceEx();
+ if (serviceEx == null) {
+ return;
+ }
+ final AtomicInteger restPackageCount = new AtomicInteger(0);
+ for (int i = 0; i < myPackagesTableModel.getRowCount(); ++i) {
+ final int finalIndex = i;
+ final InstalledPackage pkg = getInstalledPackageAt(finalIndex);
+ restPackageCount.incrementAndGet();
+ serviceEx.fetchLatestVersion(pkg.getName(), new CatchingConsumer<String, Exception>() {
+
+ private void decrement() {
+ if (restPackageCount.decrementAndGet() == 0) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ myPackagesTable.setPaintBusy(false);
+ }
+ }, ModalityState.any());
+ }
+ }
+
+ @Override
+ public void consume(Exception e) {
+ decrement();
+ }
+
+ @Override
+ public void consume(@Nullable final String latestVersion) {
+ if (latestVersion == null) {
+ decrement();
+ return;
+ }
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (finalIndex < myPackagesTableModel.getRowCount()) {
+ InstalledPackage p = getInstalledPackageAt(finalIndex);
+ if (pkg == p) {
+ myPackagesTableModel.setValueAt(latestVersion, finalIndex, 2);
+ }
+ }
+ decrement();
+ }
+ }, ModalityState.any());
+ }
+ });
+ }
+ }
+
+ private boolean shouldFetchLatestVersionsForOnlyInstalledPackages() {
+ PackageManagementServiceEx serviceEx = getServiceEx();
+ if (serviceEx != null) {
+ return serviceEx.shouldFetchLatestVersionsForOnlyInstalledPackages();
+ }
+ return false;
+ }
+
private void refreshLatestVersions() {
final Application application = ApplicationManager.getApplication();
application.executeOnPooledThread(new Runnable() {
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java b/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java
index 8b53fe6b2747..7fb47ac0dbce 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java
@@ -1,5 +1,6 @@
package com.intellij.webcore.packaging;
+import com.intellij.util.CatchingConsumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -12,4 +13,8 @@ public abstract class PackageManagementServiceEx extends PackageManagementServic
@Nullable String version,
@NotNull Listener listener);
+ public abstract boolean shouldFetchLatestVersionsForOnlyInstalledPackages();
+
+ public abstract void fetchLatestVersion(@NotNull String packageName, @NotNull final CatchingConsumer<String, Exception> consumer);
+
}
diff --git a/platform/platform-api/src/com/intellij/util/net/CertificatesManager.java b/platform/platform-api/src/com/intellij/util/net/CertificatesManager.java
new file mode 100644
index 000000000000..1a6618664756
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/CertificatesManager.java
@@ -0,0 +1,318 @@
+package com.intellij.util.net;
+
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.StreamUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * {@code CertificatesManager} is responsible for negotiation SSL connection with server
+ * that using trusted or self-signed certificates.
+ *
+ * @author Mikhail Golubev
+ */
+public class CertificatesManager {
+ private static final Logger LOG = Logger.getInstance(CertificatesManager.class);
+ private static final X509Certificate[] NO_CERTIFICATES = new X509Certificate[0];
+
+ @NonNls private static final String DEFAULT_PATH = FileUtil.join(PathManager.getSystemPath(), "tasks", "cacerts");
+ @NonNls private static final String DEFAULT_PASSWORD = "changeit";
+
+ @NotNull
+ public static CertificatesManager createDefault() {
+ return createInstance(DEFAULT_PATH, DEFAULT_PASSWORD);
+ }
+
+
+ @NotNull
+ public static CertificatesManager createInstance(@NotNull String cacertsPath, @NotNull String cacertsPassword) {
+ return new CertificatesManager(cacertsPath, cacertsPassword);
+ }
+
+ private final String myCacertsPath;
+ private final String myPassword;
+
+ private CertificatesManager(@NotNull String cacertsPath, @NotNull String cacertsPassword) {
+ myCacertsPath = cacertsPath;
+ myPassword = cacertsPassword;
+ }
+
+ /**
+ * Creates special kind of {@code SSLContext} which X509TrustManager first checks certificate presence in
+ * in default system-wide trust store (usually located at {@code ${JAVA_HOME}/lib/security/cacerts} or specified by
+ * {@code javax.net.ssl.trustStore} property) and when in the one specified by first argument of factory method
+ * {@link CertificatesManager#createInstance(String, String)}.
+ * If certificate wasn't found in either, manager will ask user whether it can be
+ * accepted (like web-browsers do) and if can, certificate will be added to specified trust store.
+ * </p>
+ * This method may be used for transition to HttpClient 4.x (see {@code HttpClients.custom().setSslContext(SSLContext)})
+ *
+ * @return instance of SSLContext with described behavior
+ */
+ @NotNull
+ public SSLContext createSslContext() throws Exception {
+ // SSLContext context = SSLContext.getDefault();
+ SSLContext context = SSLContext.getInstance("TLS");
+ TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ factory.init((KeyStore)null);
+ // assume that only X509 TrustManagers exist
+ X509TrustManager systemManager = findX509TrustManager(factory.getTrustManagers());
+
+ MutableX509TrustManager customManager = new MutableX509TrustManager(myCacertsPath, myPassword);
+ MyX509TrustManager trustManager = new MyX509TrustManager(systemManager, customManager);
+ // use default key store and secure random
+ context.init(null, new TrustManager[]{trustManager}, null);
+ return context;
+ }
+
+
+ private static class MyX509TrustManager implements X509TrustManager {
+ private final X509TrustManager mySystemManager;
+ private final MutableX509TrustManager myCustomManager;
+
+
+ private MyX509TrustManager(X509TrustManager system, MutableX509TrustManager custom) {
+ mySystemManager = system;
+ myCustomManager = custom;
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] certificates, String s) throws CertificateException {
+ // Not called by client
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void checkServerTrusted(final X509Certificate[] certificates, String s) throws CertificateException {
+ try {
+ mySystemManager.checkServerTrusted(certificates, s);
+ }
+ catch (CertificateException e1) {
+ X509Certificate certificate = certificates[0];
+ // looks like self-signed certificate
+ if (certificates.length == 1 && certificateIsSelfSigned(certificate)) {
+ // check-then-act sequence
+ synchronized (myCustomManager) {
+ try {
+ myCustomManager.checkServerTrusted(certificates, s);
+ }
+ catch (CertificateException e2) {
+ if (myCustomManager.isBroken() || !updateTrustStore(certificate)) {
+ throw e1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private boolean updateTrustStore(final X509Certificate certificate) {
+ Application app = ApplicationManager.getApplication();
+ if (app.isUnitTestMode() || app.isHeadlessEnvironment()) {
+ myCustomManager.addCertificate(certificate);
+ return true;
+ }
+
+ // can't use Application#invokeAndWait because of ReadAction
+ final CountDownLatch proceeded = new CountDownLatch(1);
+ final AtomicBoolean accepted = new AtomicBoolean();
+ app.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ UntrustedCertificateWarningDialog dialog =
+ new UntrustedCertificateWarningDialog(certificate, myCustomManager.myPath, myCustomManager.myPassword);
+ accepted.set(dialog.showAndGet());
+ if (accepted.get()) {
+ LOG.debug("Certificate was accepted");
+ myCustomManager.addCertificate(certificate);
+ }
+ }
+ finally {
+ proceeded.countDown();
+ }
+ }
+ }, ModalityState.any());
+ try {
+ proceeded.await();
+ }
+ catch (InterruptedException e) {
+ LOG.error(e);
+ }
+ return accepted.get();
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return mySystemManager.getAcceptedIssuers();
+ }
+ }
+
+ /**
+ * Trust manager that supports addition of new certificates (most likely self-signed) to corresponding physical
+ * key store.
+ */
+ private static class MutableX509TrustManager implements X509TrustManager {
+ private final String myPath;
+ private final String myPassword;
+ private final TrustManagerFactory myFactory;
+ private final KeyStore myKeyStore;
+ private volatile X509TrustManager myTrustManager;
+ private volatile boolean broken = false;
+
+ private MutableX509TrustManager(@NotNull String path, @NotNull String password) {
+ myPath = path;
+ myPassword = password;
+ myKeyStore = loadKeyStore(path, password);
+ myFactory = createFactory();
+ myTrustManager = initFactoryAndGetManager();
+ }
+
+ private TrustManagerFactory createFactory() {
+ try {
+ return TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ }
+ catch (NoSuchAlgorithmException e) {
+ LOG.error(e);
+ broken = true;
+ }
+ return null;
+ }
+
+ private KeyStore loadKeyStore(String path, String password) {
+ KeyStore keyStore = null;
+ try {
+ keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ File cacertsFile = new File(path);
+ if (cacertsFile.exists()) {
+ FileInputStream stream = null;
+ try {
+ stream = new FileInputStream(path);
+ keyStore.load(stream, password.toCharArray());
+ }
+ finally {
+ StreamUtil.closeStream(stream);
+ }
+ }
+ else {
+ FileUtil.createParentDirs(cacertsFile);
+ keyStore.load(null, password.toCharArray());
+ }
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ broken = true;
+ }
+ return keyStore;
+ }
+
+ public boolean addCertificate(X509Certificate certificate) {
+ if (broken) {
+ return false;
+ }
+ String alias = certificate.getIssuerX500Principal().getName();
+ FileOutputStream stream = null;
+ try {
+ myKeyStore.setCertificateEntry(alias, certificate);
+ stream = new FileOutputStream(myPath);
+ myKeyStore.store(stream, myPassword.toCharArray());
+ // trust manager should be updated each time its key store was modified
+ myTrustManager = initFactoryAndGetManager();
+ return true;
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ return false;
+ }
+ finally {
+ StreamUtil.closeStream(stream);
+ }
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] certificates, String s) throws CertificateException {
+ if (keyStoreIsEmpty() || broken) {
+ throw new CertificateException();
+ }
+ myTrustManager.checkClientTrusted(certificates, s);
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] certificates, String s) throws CertificateException {
+ if (keyStoreIsEmpty() || broken) {
+ throw new CertificateException();
+ }
+ myTrustManager.checkServerTrusted(certificates, s);
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ // trust no one if broken
+ if (keyStoreIsEmpty() || broken) {
+ return NO_CERTIFICATES;
+ }
+ return myTrustManager.getAcceptedIssuers();
+ }
+
+ private boolean keyStoreIsEmpty() {
+ try {
+ return myKeyStore.size() == 0;
+ }
+ catch (KeyStoreException e) {
+ LOG.error(e);
+ return true;
+ }
+ }
+
+ private X509TrustManager initFactoryAndGetManager() {
+ if (!broken) {
+ try {
+ myFactory.init(myKeyStore);
+ return findX509TrustManager(myFactory.getTrustManagers());
+ }
+ catch (KeyStoreException e) {
+ LOG.error(e);
+ broken = true;
+ }
+ }
+ return null;
+ }
+
+ public boolean isBroken() {
+ return broken;
+ }
+ }
+
+ private static X509TrustManager findX509TrustManager(TrustManager[] managers) {
+ for (TrustManager manager : managers) {
+ if (manager instanceof X509TrustManager) {
+ return (X509TrustManager)manager;
+ }
+ }
+ return null;
+ }
+
+ private static boolean certificateIsSelfSigned(X509Certificate certificate) {
+ return certificate.getIssuerX500Principal().equals(certificate.getSubjectX500Principal());
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.form b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.form
new file mode 100644
index 000000000000..c47867b508fe
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.form
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.util.net.UntrustedCertificateWarningDialog">
+ <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="10" bottom="0" right="10"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="224"/>
+ </constraints>
+ <properties>
+ <minimumSize width="-1" height="-1"/>
+ <opaque value="false"/>
+ <preferredSize width="400" height="550"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <grid id="d0af6" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="61118" class="javax.swing.JTextPane">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="400" height="50"/>
+ </grid>
+ </constraints>
+ <properties>
+ <contentType value="text/plain"/>
+ <opaque value="false"/>
+ <text value="Server's certificate is untrusted and appears to be self-signed"/>
+ </properties>
+ </component>
+ <component id="7dcbe" class="javax.swing.JLabel" binding="myWarningSign">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="ccf25" binding="myCertificateInfoPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="2" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="empty">
+ <title-color color="-16777216"/>
+ <size top="0" left="0" bottom="0" right="0"/>
+ </border>
+ <children>
+ <component id="63708" class="com.intellij.ui.components.JBLabel">
+ <constraints border-constraint="North"/>
+ <properties>
+ <font style="1"/>
+ <requestFocusEnabled value="true"/>
+ <text value="Certificate details"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="7551" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="2a804" class="javax.swing.JTextPane" binding="myNoticePane">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="2" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="50" height="50"/>
+ </grid>
+ </constraints>
+ <properties>
+ <contentType value="text/html"/>
+ <opaque value="false"/>
+ <text value="&lt;html&gt;&#10; &lt;head&gt;&#10;&#10; &lt;/head&gt;&#10; &lt;body&gt;&#10; &lt;p style=&quot;margin-top: 0&quot;&gt;&#10; &#10; &lt;/p&gt;&#10; &lt;/body&gt;&#10;&lt;/html&gt;&#10;"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <vspacer id="d6d14">
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ </children>
+ </grid>
+</form>
diff --git a/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.java b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.java
new file mode 100644
index 000000000000..b2a74ab44b9e
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.java
@@ -0,0 +1,121 @@
+package com.intellij.util.net;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.ui.IdeBorderFactory;
+import com.intellij.ui.TitledSeparator;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.FormBuilder;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.security.auth.x500.X500Principal;
+import javax.swing.*;
+import java.awt.*;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.util.Map;
+
+import static com.intellij.openapi.util.Pair.create;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class UntrustedCertificateWarningDialog extends DialogWrapper {
+ private static final Logger LOG = Logger.getInstance(UntrustedCertificateWarningDialog.class);
+ private static DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
+
+ private static final Map<String, String> FIELD_ABBREVIATIONS = ContainerUtil.newHashMap(
+ create("CN", "Common Name"),
+ create("O", "Organization"),
+ create("OU", "Organizational Unit"),
+ create("L", "Location"),
+ create("C", "Country"),
+ create("ST", "State")
+ );
+
+ private JPanel myRootPanel;
+ private JLabel myWarningSign;
+ private JPanel myCertificateInfoPanel;
+ private JTextPane myNoticePane;
+ private final X509Certificate myCertificate;
+ private final String myPath, myPassword;
+
+ public UntrustedCertificateWarningDialog(@NotNull X509Certificate certificate, @NotNull String storePath, @NotNull String password) {
+ super((Project)null, false);
+
+ myCertificate = certificate;
+ myPath = FileUtil.toCanonicalPath(storePath);
+
+ myPassword = password;
+
+ FormBuilder builder = FormBuilder.createFormBuilder();
+
+ // I'm not using separate panels and form builders to preserve alignment of labels
+ builder = updateBuilderWithTitle(builder, "Issued To");
+ builder = updateBuilderWithPrincipalData(builder, myCertificate.getSubjectX500Principal());
+ builder = updateBuilderWithTitle(builder, "Issued By");
+ builder = updateBuilderWithPrincipalData(builder, myCertificate.getIssuerX500Principal());
+ builder = updateBuilderWithTitle(builder, "Validity Period");
+ builder = builder
+ .setIndent(IdeBorderFactory.TITLED_BORDER_INDENT)
+ .addLabeledComponent("Valid from", new JBLabel(DATE_FORMAT.format(myCertificate.getNotBefore())))
+ .addLabeledComponent("Valid until", new JBLabel(DATE_FORMAT.format(myCertificate.getNotAfter())));
+ myCertificateInfoPanel.add(builder.getPanel(), BorderLayout.CENTER);
+
+ setTitle("Untrusted Server's Certificate");
+ setOKButtonText("Accept");
+ setCancelButtonText("Reject");
+ myWarningSign.setIcon(AllIcons.General.WarningDialog);
+
+ Messages.installHyperlinkSupport(myNoticePane);
+// myNoticePane.setFont(myNoticePane.getFont().deriveFont((float)FontSize.SMALL.getSize()));
+ myNoticePane.setText(
+ String.format("<html><p><small>" +
+ "Accepted certificate will be saved in truststore <code>%s</code> with password <code>%s</code>" +
+ "</small></p><html>",
+ myPath, myPassword));
+
+ init();
+ LOG.debug("Preferred size: " + getPreferredSize());
+ }
+
+ @SuppressWarnings("MethodMayBeStatic")
+ private FormBuilder updateBuilderWithPrincipalData(FormBuilder builder, X500Principal principal) {
+ builder = builder.setIndent(IdeBorderFactory.TITLED_BORDER_INDENT);
+ for (String field : principal.getName().split(",")) {
+ field = field.trim();
+ String[] parts = field.split("=", 2);
+ if (parts.length != 2) {
+ continue;
+ }
+
+ String name = parts[0];
+ String value = parts[1];
+
+ String longName = FIELD_ABBREVIATIONS.get(name.toUpperCase());
+ if (longName == null) {
+ continue;
+ }
+
+ builder = builder.addLabeledComponent(String.format("<html>%s (<b>%s</b>)</html>", longName, name), new JBLabel(value));
+ }
+ return builder.setIndent(0);
+ }
+
+ @SuppressWarnings("MethodMayBeStatic")
+ private FormBuilder updateBuilderWithTitle(FormBuilder builder, String title) {
+ return builder.addComponent(new TitledSeparator(title), IdeBorderFactory.TITLED_BORDER_TOP_INSET);
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ return myRootPanel;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java
index 03e47c519a79..dfb004f3c150 100644
--- a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java
+++ b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java
@@ -330,7 +330,8 @@ public class EditorHyperlinkSupport {
break;
}
}
- int newIndex = i > 0 ? i % ranges.size() : 0;
+ int initial = i > 0 ? i % ranges.size() : 0;
+ int newIndex = initial;
while (newIndex < ranges.size() && newIndex >= 0) {
newIndex = (newIndex + delta + ranges.size()) % ranges.size();
final RangeHighlighter next = ranges.get(newIndex);
@@ -342,7 +343,7 @@ public class EditorHyperlinkSupport {
}
}, newIndex == -1 ? -1 : newIndex + 1, ranges.size());
}
- if (newIndex == i) {
+ if (newIndex == initial) {
break; // cycled through everything, found no next/prev hyperlink
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java
index f9243cacec09..ddcfa870e4b5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.impl.*;
import com.intellij.openapi.editor.impl.softwrap.*;
import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NotNull;
@@ -340,7 +341,8 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
notifyListenersOnVisualLineStart(myContext.lineStartPosition);
- if (!myContext.exceedsVisualEdge(newX)) {
+ if (!myContext.exceedsVisualEdge(newX)
+ || (myContext.currentPosition.offset == myContext.lineStartPosition.offset) && !Registry.is("editor.wrap.collapsed.region.at.line.start")) {
myContext.advance(foldRegion, placeholderWidthInPixels);
return true;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java
index 16034e113809..092588caeb0a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java
@@ -27,8 +27,12 @@ import com.intellij.openapi.vfs.VfsBundle;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.PathUtil;
import com.intellij.util.io.UrlConnectionUtil;
+import com.intellij.util.net.CertificatesManager;
import org.jetbrains.annotations.NotNull;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSession;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
@@ -66,6 +70,21 @@ public class DefaultRemoteContentProvider extends RemoteContentProvider {
HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection();
connection.setConnectTimeout(CONNECT_TIMEOUT);
connection.setReadTimeout(READ_TIMEOUT);
+ if (connection instanceof HttpsURLConnection) {
+ try {
+ HttpsURLConnection httpsConnection = (HttpsURLConnection)connection;
+ httpsConnection.setHostnameVerifier(new HostnameVerifier() {
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ });
+ httpsConnection.setSSLSocketFactory(CertificatesManager.createDefault().createSslContext().getSocketFactory());
+ }
+ catch (Exception e) {
+ LOG.warn(e);
+ }
+ }
input = UrlConnectionUtil.getConnectionInputStreamWithException(connection, new EmptyProgressIndicator());
final int responseCode = connection.getResponseCode();
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java
index 96b5818f59f3..eaa1e63977c5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java
@@ -480,7 +480,9 @@ public class IdeFrameImpl extends JFrame implements IdeFrameEx, DataProvider {
}
public void storeFullScreenStateIfNeeded() {
- storeFullScreenStateIfNeeded(myFrameDecorator.isInFullScreen());
+ if (myFrameDecorator != null) {
+ storeFullScreenStateIfNeeded(myFrameDecorator.isInFullScreen());
+ }
}
public void storeFullScreenStateIfNeeded(boolean state) {
diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java
index 96bb850d0899..5565e77a8cfb 100644
--- a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java
+++ b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java
@@ -6,6 +6,8 @@ import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.ImmediateEventExecutor;
import org.jetbrains.annotations.NotNull;
+import java.util.concurrent.TimeUnit;
+
@ChannelHandler.Sharable
public final class ChannelRegistrar extends ChannelInboundHandlerAdapter {
private final ChannelGroup openChannels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
@@ -43,7 +45,7 @@ public final class ChannelRegistrar extends ChannelInboundHandlerAdapter {
}
try {
- openChannels.close().awaitUninterruptibly();
+ openChannels.close().awaitUninterruptibly(30, TimeUnit.SECONDS);
}
finally {
if (eventLoopGroup != null) {
diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties
index caaef0b5491b..fdc8e12b4bce 100644
--- a/platform/platform-resources-en/src/misc/registry.properties
+++ b/platform/platform-resources-en/src/misc/registry.properties
@@ -355,4 +355,5 @@ show.all.look.and.feels=false
show.all.look.and.feels.description=Make accessible all available Look and Feels
cvs.roots.refresh.uses.vfs=true
cvs.roots.refresh.uses.vfs.description=Should CVS roots refresh after update use VFS
+editor.wrap.collapsed.region.at.line.start=false
diff --git a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java
index 842ecfc5f160..6c0a9f10886b 100644
--- a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@ package com.intellij.ide.bookmarks;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.LogicalPosition;
-import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest;
+import com.intellij.openapi.editor.impl.AbstractEditorTest;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.vfs.VfsUtil;
@@ -34,7 +34,7 @@ import java.util.List;
* @author Denis Zhdanov
* @since 12/27/10 1:43 PM
*/
-public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModificationTest {
+public class BookmarkManagerTest extends AbstractEditorTest {
private final List<Bookmark> myBookmarks = new ArrayList<Bookmark>();
@Override
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
index c49532ca9315..be8801949905 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ import java.util.regex.Pattern;
* @author Denis Zhdanov
* @since 11/18/10 7:43 PM
*/
-public abstract class AbstractEditorProcessingOnDocumentModificationTest extends LightPlatformCodeInsightTestCase {
+public abstract class AbstractEditorTest extends LightPlatformCodeInsightTestCase {
protected void init(@NotNull @NonNls String fileText, @NotNull TestFileType type) throws IOException {
configureFromFileText(getFileName(type), fileText);
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java
new file mode 100644
index 000000000000..770d05621ad6
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor.impl.softwrap;
+
+import com.intellij.openapi.editor.FoldRegion;
+import com.intellij.openapi.editor.SoftWrap;
+import com.intellij.openapi.editor.impl.AbstractEditorTest;
+import com.intellij.testFramework.EditorTestUtil;
+import com.intellij.testFramework.TestFileType;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class SoftWrapTest extends AbstractEditorTest {
+
+ public void testCollapsedRegionWithLongPlaceholderAtLineStart1() throws IOException {
+ doTestSoftWraps(10, "<fold text='veryVeryVeryLongPlaceholder'>foo</fold>");
+ }
+
+ public void testCollapsedRegionWithLongPlaceholderAtLineStart2() throws IOException {
+ doTestSoftWraps(10, "<fold text='veryVeryVeryLongPlaceholder'>foo</fold><wrap>bar");
+ }
+
+ public void testCollapsedRegionWithLongPlaceholderAtLineStart3() throws IOException {
+ doTestSoftWraps(10, "<fold text='veryVeryVeryLongPlaceholder'>foo</fold>\nvery long <wrap>text");
+ }
+
+ private static final String TAGS_PATTERN = "(<fold(\\stext=\'([^\']*)\')?>)|(</fold>)|<wrap>";
+
+ private void doTestSoftWraps(int wrapWidth, String text) throws IOException {
+ List<MyFoldRegion> foldRegions = new ArrayList<MyFoldRegion>();
+ List<Integer> wrapPositions = new ArrayList<Integer>();
+ int foldInsertPosition = 0;
+ int pos = 0;
+ int docPos = 0;
+ Matcher matcher = Pattern.compile(TAGS_PATTERN).matcher(text);
+ StringBuilder cleanedText = new StringBuilder();
+ while(matcher.find()) {
+ cleanedText.append(text.substring(pos, matcher.start()));
+ docPos += matcher.start() - pos;
+ pos = matcher.end();
+ if (matcher.group(1) != null) { // <fold>
+ foldRegions.add(foldInsertPosition++, new MyFoldRegion(docPos, matcher.group(3), matcher.group(2) != null));
+ }
+ else if (matcher.group(4) != null) { // </fold>
+ assertTrue("Misplaced closing fold marker tag: " + text, foldInsertPosition > 0);
+ foldRegions.get(--foldInsertPosition).endPos = docPos;
+ }
+ else { // <wrap>
+ wrapPositions.add(docPos);
+ }
+ }
+ assertTrue("Missing closing fold marker tag: " + text, foldInsertPosition == 0);
+ cleanedText.append(text.substring(pos));
+
+ init(cleanedText.toString(), TestFileType.TEXT);
+
+ for (MyFoldRegion region : foldRegions) {
+ FoldRegion r = addFoldRegion(region.startPos, region.endPos, region.placeholder);
+ if (region.collapse) {
+ toggleFoldRegionState(r, false);
+ }
+ }
+
+ EditorTestUtil.configureSoftWraps(myEditor, wrapWidth);
+
+ List<Integer> actualWrapPositions = new ArrayList<Integer>();
+ for (SoftWrap wrap : myEditor.getSoftWrapModel().getSoftWrapsForRange(0, myEditor.getDocument().getTextLength())) {
+ actualWrapPositions.add(wrap.getStart());
+ }
+ assertEquals("Wrong wrap positions", wrapPositions, actualWrapPositions);
+ }
+
+ private static class MyFoldRegion {
+ private final int startPos;
+ private int endPos;
+ private final String placeholder;
+ private final boolean collapse;
+
+ private MyFoldRegion(int pos, String placeholder, boolean collapse) {
+ this.startPos = pos;
+ this.placeholder = placeholder;
+ this.collapse = collapse;
+ }
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java
index bb15dbc655f2..c5e4b9555b6e 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java
@@ -17,13 +17,13 @@ package com.intellij.openapi.editor.impl.softwrap.mapping;
import com.intellij.codeInsight.folding.CodeFoldingManager;
import com.intellij.openapi.editor.*;
-import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest;
-import com.intellij.openapi.editor.impl.DefaultEditorTextRepresentationHelper;
+import com.intellij.openapi.editor.impl.AbstractEditorTest;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.TestFileType;
import gnu.trove.TIntHashSet;
import gnu.trove.TIntProcedure;
@@ -38,7 +38,7 @@ import java.util.List;
* @author Denis Zhdanov
* @since 09/16/2010
*/
-public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorProcessingOnDocumentModificationTest {
+public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorTest {
private boolean mySmartHome;
@@ -1055,28 +1055,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
private void init(final int visibleWidth, @NotNull String fileText, @NotNull TestFileType fileType, final int symbolWidth) throws IOException {
init(fileText, fileType);
- myEditor.getSettings().setUseSoftWraps(true);
- SoftWrapModelImpl model = (SoftWrapModelImpl)myEditor.getSoftWrapModel();
- model.reinitSettings();
-
- SoftWrapApplianceManager applianceManager = model.getApplianceManager();
- applianceManager.setWidthProvider(new SoftWrapApplianceManager.VisibleAreaWidthProvider() {
- @Override
- public int getVisibleAreaWidth() {
- return visibleWidth;
- }
- });
-
- if (symbolWidth > 0) {
- applianceManager.setRepresentationHelper(new DefaultEditorTextRepresentationHelper(myEditor) {
- @Override
- public int charWidth(char c, int fontType) {
- return symbolWidth;
- }
- });
- }
-
- applianceManager.registerSoftWrapIfNecessary();
+ EditorTestUtil.configureSoftWraps(myEditor, visibleWidth, symbolWidth);
}
private static void checkSoftWraps(int... startOffsets) {
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java
index 80998a056091..22ebe09a45b2 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java
@@ -137,6 +137,7 @@ public class GeneralIdBasedToSMTRunnerEventsConvertor extends GeneralTestEventsP
if (node != null) {
if (node.getState() == State.REGISTERED && startedNodeEvent.isRunning()) {
node.setState(State.RUNNING);
+ myRunningNodes.add(node);
node.getProxy().setStarted();
if (suite) {
fireOnSuiteStarted(node.getProxy());
@@ -172,13 +173,13 @@ public class GeneralIdBasedToSMTRunnerEventsConvertor extends GeneralTestEventsP
State initialState = startedNodeEvent.isRunning() ? State.RUNNING : State.REGISTERED;
node = new Node(startedNodeEvent.getId(), parentNode, childProxy, initialState);
myNodeByIdMap.put(startedNodeEvent.getId(), node);
- myRunningNodes.add(node);
if (myLocator != null) {
childProxy.setLocator(myLocator);
}
parentNode.getProxy().addChild(childProxy);
if (node.getState() == State.RUNNING) {
+ myRunningNodes.add(node);
// progress started
childProxy.setStarted();
if (suite) {
@@ -512,7 +513,7 @@ public class GeneralIdBasedToSMTRunnerEventsConvertor extends GeneralTestEventsP
}
}
if (runningLeaves.isEmpty()) {
- throw new RuntimeException("No running leaves found, running nodes: " + myRunningNodes);
+ return myTestsRootNode;
}
if (runningLeaves.size() == 1) {
return runningLeaves.iterator().next();
diff --git a/platform/testFramework/src/com/intellij/testFramework/ActionTestCase.java b/platform/testFramework/src/com/intellij/testFramework/ActionTestCase.java
new file mode 100644
index 000000000000..7bc16e7db44b
--- /dev/null
+++ b/platform/testFramework/src/com/intellij/testFramework/ActionTestCase.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.testFramework;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.CaretModel;
+import com.intellij.openapi.editor.VisualPosition;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
+import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
+import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
+import com.intellij.testFramework.fixtures.TestFixtureBuilder;
+import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: Andrey.Vokin
+ * Date: 11/26/13
+ */
+public abstract class ActionTestCase extends UsefulTestCase {
+ public static final String CARET_TAG_REPLACE_REGEX = EditorTestUtil.CARET_TAG_PREFIX + "(\\+\\d+)?>";
+ protected CodeInsightTestFixture myFixture;
+
+ protected abstract FileType getFileType();
+
+ protected abstract String getTestDataPath();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final IdeaTestFixtureFactory factory = IdeaTestFixtureFactory.getFixtureFactory();
+ final TestFixtureBuilder<IdeaProjectTestFixture> fixtureBuilder = factory.createLightFixtureBuilder(null);
+ final IdeaProjectTestFixture fixture = fixtureBuilder.getFixture();
+ myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(fixture, new LightTempDirTestFixtureImpl(true));
+ myFixture.setUp();
+ myFixture.setTestDataPath(getTestDataPath());
+ }
+
+
+ @Override
+ protected void tearDown() throws Exception {
+ myFixture.tearDown();
+ myFixture = null;
+ super.tearDown();
+ }
+
+ protected void doAction(@NotNull final String before, @NotNull String expected, @NotNull final Runnable action) {
+ int[] caretAndSelectionPositionInSourceFile = EditorTestUtil.getCaretAndSelectionPosition(before);
+ int[] caretAndSelectionPositionInExpectedFile = EditorTestUtil.getCaretAndSelectionPosition(expected);
+
+ final String sourceFinal = before.replaceAll(CARET_TAG_REPLACE_REGEX, "").replace(EditorTestUtil.SELECTION_START_TAG, "").replace(EditorTestUtil.SELECTION_END_TAG, "");
+ final String expectedFinal = expected.replaceAll(CARET_TAG_REPLACE_REGEX, "").replace(EditorTestUtil.SELECTION_START_TAG, "").replace(EditorTestUtil.SELECTION_END_TAG, "");
+
+ final PsiFile file = myFixture.configureByText(getFileType(), sourceFinal);
+ myFixture.getEditor().getSettings().setVirtualSpace(true);
+ if (caretAndSelectionPositionInSourceFile[0] >= 0) {
+ CaretModel caretModel = myFixture.getEditor().getCaretModel();
+ caretModel.moveToOffset(caretAndSelectionPositionInSourceFile[0]);
+ if (caretAndSelectionPositionInSourceFile[1] != 0) {
+ int line = caretModel.getVisualPosition().getLine();
+ int column = caretModel.getVisualPosition().getColumn();
+ caretModel.moveToVisualPosition(new VisualPosition(line, column + caretAndSelectionPositionInSourceFile[1]));
+ }
+ }
+
+ if (caretAndSelectionPositionInSourceFile[2] >= 0) {
+ myFixture.getEditor().getSelectionModel()
+ .setSelection(caretAndSelectionPositionInSourceFile[2], caretAndSelectionPositionInSourceFile[3]);
+ }
+
+ ApplicationManager.getApplication().runWriteAction(action);
+
+ if (caretAndSelectionPositionInExpectedFile[0] >= 0) {
+ assertEquals(caretAndSelectionPositionInExpectedFile[0], myFixture.getCaretOffset());
+ if (caretAndSelectionPositionInExpectedFile[1] != 0) {
+ assertEquals(caretAndSelectionPositionInExpectedFile[1], myFixture.getEditor().getCaretModel().getVisualPosition().getColumn());
+ }
+ }
+ if (caretAndSelectionPositionInExpectedFile[2] >= 0) {
+ assertEquals(caretAndSelectionPositionInExpectedFile[2], myFixture.getEditor().getSelectionModel().getSelectionStart());
+ assertEquals(caretAndSelectionPositionInExpectedFile[3], myFixture.getEditor().getSelectionModel().getSelectionEnd());
+ }
+
+ assertEquals(expectedFinal, myFixture.getDocument(file).getText());
+ }
+}
diff --git a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
index 5f7eb538fedb..2400ed5ee355 100644
--- a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,9 @@ import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.TypedAction;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.editor.impl.DefaultEditorTextRepresentationHelper;
+import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
+import com.intellij.openapi.editor.impl.softwrap.mapping.SoftWrapApplianceManager;
import com.intellij.psi.tree.IElementType;
import junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
@@ -132,4 +135,42 @@ public class EditorTestUtil {
return new int[]{caretPosInSourceFile, visualColumnOffset, selectionStartInSourceFile, selectionEndInSourceFile};
}
+
+ /**
+ * Configures given editor to wrap at given character count.
+ *
+ * @return whether any actual wraps of editor contents were created as a result of turning on soft wraps
+ */
+ public static boolean configureSoftWraps(Editor editor, final int charCountToWrapAt) {
+ int charWidthInPixels = 7;
+ // we're adding 1 to charCountToWrapAt, to account for wrap character width, and 1 to overall width to overcome wrapping logic subtleties
+ return configureSoftWraps(editor, (charCountToWrapAt + 1) * charWidthInPixels + 1, charWidthInPixels);
+ }
+
+ /**
+ * Configures given editor to wrap at given width, assuming characters are of given width
+ *
+ * @return whether any actual wraps of editor contents were created as a result of turning on soft wraps
+ */
+ public static boolean configureSoftWraps(Editor editor, final int visibleWidth, final int charWidthInPixels) {
+ editor.getSettings().setUseSoftWraps(true);
+ SoftWrapModelImpl model = (SoftWrapModelImpl)editor.getSoftWrapModel();
+ model.reinitSettings();
+
+ SoftWrapApplianceManager applianceManager = model.getApplianceManager();
+ applianceManager.setWidthProvider(new SoftWrapApplianceManager.VisibleAreaWidthProvider() {
+ @Override
+ public int getVisibleAreaWidth() {
+ return visibleWidth;
+ }
+ });
+ applianceManager.setRepresentationHelper(new DefaultEditorTextRepresentationHelper(editor) {
+ @Override
+ public int charWidth(char c, int fontType) {
+ return charWidthInPixels;
+ }
+ });
+ applianceManager.registerSoftWrapIfNecessary();
+ return !model.getRegisteredSoftWraps().isEmpty();
+ }
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java
index 071dd4b3a22b..ed629b9ca353 100644
--- a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java
@@ -34,7 +34,6 @@ import com.intellij.openapi.options.SchemesManagerFactory;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
import com.intellij.openapi.startup.StartupManager;
-import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -46,7 +45,6 @@ import com.intellij.psi.impl.PsiFileFactoryImpl;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl;
import com.intellij.psi.util.CachedValuesManager;
-import com.intellij.rt.execution.junit.FileComparisonFailure;
import com.intellij.util.CachedValuesManagerImpl;
import com.intellij.util.Function;
import com.intellij.util.messages.MessageBus;
@@ -57,7 +55,6 @@ import org.picocontainer.*;
import org.picocontainer.defaults.AbstractComponentAdapter;
import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Set;
@@ -272,22 +269,8 @@ public abstract class ParsingTestCase extends PlatformLiteFixture {
}
public static void doCheckResult(String fullPath, String targetDataName, String text) throws IOException {
- text = text.trim();
String expectedFileName = fullPath + File.separatorChar + targetDataName;
- if (OVERWRITE_TESTDATA) {
- VfsTestUtil.overwriteTestData(expectedFileName, text);
- System.out.println("File " + expectedFileName + " created.");
- }
- try {
- String expectedText = doLoadFile(fullPath, targetDataName);
- if (!Comparing.equal(expectedText, text)) {
- throw new FileComparisonFailure(targetDataName, expectedText, text, expectedFileName);
- }
- }
- catch(FileNotFoundException e){
- VfsTestUtil.overwriteTestData(expectedFileName, text);
- fail("No output text found. File " + expectedFileName + " created.");
- }
+ UsefulTestCase.assertSameLinesWithFile(expectedFileName, text);
}
protected static String toParseTreeText(final PsiElement file, boolean skipSpaces, boolean printRanges) {
diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
index 193fab53e851..5c262a0f0517 100644
--- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileVisitor;
@@ -57,6 +58,7 @@ import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@@ -687,10 +689,14 @@ public abstract class UsefulTestCase extends TestCase {
String fileText;
try {
if (OVERWRITE_TESTDATA) {
- FileUtil.writeToFile(new File(filePath), actualText);
+ VfsTestUtil.overwriteTestData(filePath, actualText);
System.out.println("File " + filePath + " created.");
}
- fileText = FileUtil.loadFile(new File(filePath));
+ fileText = FileUtil.loadFile(new File(filePath), CharsetToolkit.UTF8);
+ }
+ catch (FileNotFoundException e) {
+ VfsTestUtil.overwriteTestData(filePath, actualText);
+ throw new AssertionFailedError("No output text found. File " + filePath + " created.");
}
catch (IOException e) {
throw new RuntimeException(e);
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java
index 23c60fb3651d..e7c2e827cc06 100644
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java
+++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java
@@ -194,9 +194,6 @@ public class GraphBuilder {
// local package
@NotNull
public MutableGraph runBuild(@NotNull List<? extends GraphCommit> commitParentses) {
- if (commitParentses.size() == 0) {
- throw new IllegalArgumentException("Empty list commitParentses");
- }
for (GraphCommit vcsCommit : commitParentses) {
append(vcsCommit);
}
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java
index a6fd7c1a93ea..4f052f5209fc 100644
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java
+++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java
@@ -1,5 +1,6 @@
package com.intellij.vcs.log.graphmodel.impl;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.vcs.log.GraphCommit;
@@ -30,6 +31,8 @@ public class GraphModelImpl implements GraphModel {
private final List<Consumer<UpdateRequest>> listeners = new ArrayList<Consumer<UpdateRequest>>();
private final GraphBranchShowFixer branchShowFixer;
+ private static final Logger LOG = Logger.getInstance(GraphModelImpl.class);
+
private Function<Node, Boolean> isStartedBranchVisibilityNode = new Function<Node, Boolean>() {
@NotNull
@Override
@@ -81,8 +84,15 @@ public class GraphModelImpl implements GraphModel {
graph.updateVisibleRows();
int newSize = graph.getNodeRows().size();
- int newTo = newSize == 0 ? 0 : newSize - 1;
- int oldTo = oldSize == 0 ? 0 : oldSize - 1;
+ if (newSize == 0) { // empty log. Possible only right after git init
+ return;
+ }
+ if (oldSize == 0) { // this shouldn't happen unless the log is empty
+ LOG.error("Old size can't be 0 if newSize is not 0. newSize: " + newSize);
+ return;
+ }
+ int newTo = newSize - 1;
+ int oldTo = oldSize - 1;
UpdateRequest updateRequest = UpdateRequest.buildFromToInterval(0, oldTo, 0, newTo);
callUpdateListener(updateRequest);
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java
index 266cb14e271a..1b75ba5f7102 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java
@@ -776,7 +776,7 @@ public class VcsLogDataHolder implements Disposable {
}
public boolean isFullLogReady() {
- return myFullLog;
+ return myFullLog && getTopCommitsCount() > 0;
}
@NotNull
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java
index 940add3775ad..11f7540afd3e 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java
@@ -15,8 +15,12 @@
*/
package com.intellij.vcs.log.data;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.ThrowableComputable;
+import com.intellij.util.io.IOUtil;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.io.Page;
import com.intellij.util.io.PersistentEnumerator;
@@ -33,15 +37,21 @@ import java.io.IOException;
/**
* Supports the int <-> Hash persistent mapping.
*/
-class VcsLogHashMap {
+class VcsLogHashMap implements Disposable {
private static final File LOG_CACHE_APP_DIR = new File(PathManager.getSystemPath(), "vcs-log");
+ private static final Logger LOG = Logger.getInstance(VcsLogHashMap.class);
private final PersistentEnumerator<Hash> myPersistentEnumerator;
VcsLogHashMap(@NotNull Project project) throws IOException {
- File myMapFile = new File(LOG_CACHE_APP_DIR, project.getName() + "." + project.getLocationHash());
- myPersistentEnumerator = new PersistentEnumerator<Hash>(myMapFile, new MyHashKeyDescriptor(), Page.PAGE_SIZE);
+ final File myMapFile = new File(LOG_CACHE_APP_DIR, project.getName() + "." + project.getLocationHash());
+ myPersistentEnumerator = IOUtil.openCleanOrResetBroken(new ThrowableComputable<PersistentEnumerator<Hash>, IOException>() {
+ @Override
+ public PersistentEnumerator<Hash> compute() throws IOException {
+ return new PersistentEnumerator<Hash>(myMapFile, new MyHashKeyDescriptor(), Page.PAGE_SIZE);
+ }
+ }, myMapFile);
}
@Nullable
@@ -53,6 +63,16 @@ class VcsLogHashMap {
return myPersistentEnumerator.enumerate(hash);
}
+ @Override
+ public void dispose() {
+ try {
+ myPersistentEnumerator.close();
+ }
+ catch (IOException e) {
+ LOG.warn(e);
+ }
+ }
+
private static class MyHashKeyDescriptor implements KeyDescriptor<Hash> {
@Override
public void save(DataOutput out, Hash value) throws IOException {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java
index c15af9fd5afc..fae4fa71d63b 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java
@@ -3,6 +3,7 @@ package com.intellij.vcs.log.ui;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsLog;
@@ -21,12 +22,14 @@ import com.intellij.vcs.log.impl.VcsLogImpl;
import com.intellij.vcs.log.printmodel.SelectController;
import com.intellij.vcs.log.ui.frame.MainFrame;
import com.intellij.vcs.log.ui.frame.VcsLogGraphTable;
+import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.table.TableModel;
import java.awt.*;
import java.util.Collection;
+import java.util.Set;
/**
* @author erokhins
@@ -82,8 +85,49 @@ public class VcsLogUI {
});
}
- public void setModel(@NotNull TableModel model) {
- myMainFrame.getGraphTable().setModel(model);
+ public void setModel(@NotNull AbstractVcsLogTableModel model) {
+ VcsLogGraphTable table = getTable();
+ int[] selectedRows = table.getSelectedRows();
+ TableModel previousModel = table.getModel();
+
+ table.setModel(model);
+
+ if (previousModel instanceof AbstractVcsLogTableModel) { // initially it is an empty DefaultTableModel
+ restoreSelection(table, (AbstractVcsLogTableModel)previousModel, selectedRows, model);
+ }
+ }
+
+ private static void restoreSelection(@NotNull VcsLogGraphTable table, @NotNull AbstractVcsLogTableModel previousModel,
+ int[] previousSelectedRows, @NotNull AbstractVcsLogTableModel newModel) {
+ Set<Hash> selectedHashes = getHashesAtRows(previousModel, previousSelectedRows);
+ Set<Integer> rowsToSelect = findNewRowsToSelect(newModel, selectedHashes);
+ for (Integer row : rowsToSelect) {
+ table.addRowSelectionInterval(row, row);
+ }
+ }
+
+ @NotNull
+ private static Set<Hash> getHashesAtRows(@NotNull AbstractVcsLogTableModel model, int[] rows) {
+ Set<Hash> hashes = ContainerUtil.newHashSet();
+ for (int row : rows) {
+ Hash hash = model.getHashAtRow(row);
+ if (hash != null) {
+ hashes.add(hash);
+ }
+ }
+ return hashes;
+ }
+
+ @NotNull
+ private static Set<Integer> findNewRowsToSelect(@NotNull AbstractVcsLogTableModel model, @NotNull Set<Hash> selectedHashes) {
+ Set<Integer> rowsToSelect = ContainerUtil.newHashSet();
+ for (int row = 0; row < model.getRowCount() && rowsToSelect.size() < selectedHashes.size(); row++) {//stop iterating if found all hashes
+ Hash hash = model.getHashAtRow(row);
+ if (hash != null && selectedHashes.contains(hash)) {
+ rowsToSelect.add(row);
+ }
+ }
+ return rowsToSelect;
}
public void updateUI() {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java
index 44f58ddc67ae..f4401af18e4d 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java
@@ -61,6 +61,10 @@ public class BranchesPanel extends JPanel {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
+ if (!myUI.getMainFrame().areGraphActionsEnabled()) {
+ return;
+ }
+
final RefGroup group = findRef(e);
if (group == null) {
return;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java
index 248bfd932c5c..ef79df6275bd 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java
@@ -188,8 +188,12 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
private final JTextField myBranchesList;
ContainingBranchesPanel() {
- JLabel label = new JBLabel("Contained in branches: ");
- label.setFont(label.getFont().deriveFont(Font.ITALIC));
+ JLabel label = new JBLabel("Contained in branches: ") {
+ @Override
+ public Font getFont() {
+ return UIUtil.getLabelFont().deriveFont(Font.ITALIC);
+ }
+ };
myLoadingIcon = new AsyncProcessIcon("Loading...");
myBranchesList = new JBTextField("");
myBranchesList.setEditable(false);
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java
index 8c6fd2f2486a..b41f98fb24f6 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java
@@ -24,6 +24,7 @@ import com.intellij.vcs.log.data.VcsLogUiProperties;
import com.intellij.vcs.log.ui.VcsLogUI;
import com.intellij.vcs.log.ui.filter.VcsLogClassicFilterUi;
import com.intellij.vcs.log.ui.filter.VcsLogFilterUi;
+import com.intellij.vcs.log.ui.tables.GraphTableModel;
import icons.VcsLogIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -151,14 +152,14 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
}
private JComponent createActionsToolbar() {
- AnAction hideBranchesAction = new DumbAwareAction("Collapse linear branches", "Collapse linear branches", VcsLogIcons.CollapseBranches) {
+ AnAction hideBranchesAction = new GraphAction("Collapse linear branches", "Collapse linear branches", VcsLogIcons.CollapseBranches) {
@Override
public void actionPerformed(AnActionEvent e) {
myUI.hideAll();
}
};
- AnAction showBranchesAction = new DumbAwareAction("Expand all branches", "Expand all branches", VcsLogIcons.ExpandBranches) {
+ AnAction showBranchesAction = new GraphAction("Expand all branches", "Expand all branches", VcsLogIcons.ExpandBranches) {
@Override
public void actionPerformed(AnActionEvent e) {
myUI.showAll();
@@ -227,6 +228,10 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
return myToolbar;
}
+ public boolean areGraphActionsEnabled() {
+ return myGraphTable.getModel() instanceof GraphTableModel && myGraphTable.getRowCount() > 0;
+ }
+
private class CommitSelectionListener implements ListSelectionListener {
private final ChangesBrowser myChangesBrowser;
@@ -290,5 +295,23 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
public void setSelected(AnActionEvent e, boolean state) {
myUI.setLongEdgeVisibility(state);
}
+
+ @Override
+ public void update(AnActionEvent e) {
+ super.update(e);
+ e.getPresentation().setEnabled(areGraphActionsEnabled());
+ }
+ }
+
+ private abstract class GraphAction extends DumbAwareAction {
+
+ public GraphAction(String text, String description, Icon icon) {
+ super(text, description, icon);
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ e.getPresentation().setEnabled(areGraphActionsEnabled());
+ }
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java
index 0752ce3ebdbc..5b253d7d49e0 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java
@@ -51,16 +51,16 @@ public class GraphCommitCellRender extends AbstractPaddingCellRender {
@Override
protected int getLeftPadding(JTable table, @Nullable Object value) {
GraphCommitCell cell = (GraphCommitCell)value;
-
if (cell == null) {
return 0;
}
+ return calcPaddingBeforeText(cell, (Graphics2D)table.getGraphics());
+ }
- int refPadding = calcRefsPadding(cell.getRefsToThisCommit(), (Graphics2D)table.getGraphics());
-
+ private int calcPaddingBeforeText(GraphCommitCell cell, Graphics2D g) {
+ int refPadding = calcRefsPadding(cell.getRefsToThisCommit(), g);
int countCells = cell.getPrintCell().countCell();
int graphPadding = countCells * WIDTH_NODE;
-
return refPadding + graphPadding;
}
@@ -82,9 +82,9 @@ public class GraphCommitCellRender extends AbstractPaddingCellRender {
return;
}
- BufferedImage image = UIUtil.createImage(1000, HEIGHT_CELL, BufferedImage.TYPE_INT_ARGB);
+ int width = calcPaddingBeforeText(cell, (Graphics2D)g);
+ BufferedImage image = UIUtil.createImage(width, HEIGHT_CELL, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
- g2.setBackground(new Color(0, 0, 0, 0));
graphPainter.draw(g2, cell.getPrintCell());
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java
index 1e26910d938e..25c0397b9979 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java
@@ -14,9 +14,9 @@ import javax.swing.table.AbstractTableModel;
import java.util.List;
/**
- * @param <T> commit column class
+ * @param <CommitColumnClass> commit column class
*/
-public abstract class AbstractVcsLogTableModel<T> extends AbstractTableModel {
+public abstract class AbstractVcsLogTableModel<CommitColumnClass> extends AbstractTableModel {
public static final VirtualFile FAKE_ROOT = NullVirtualFile.INSTANCE;
@@ -80,10 +80,10 @@ public abstract class AbstractVcsLogTableModel<T> extends AbstractTableModel {
protected abstract VirtualFile getRoot(int rowIndex);
@NotNull
- protected abstract T getCommitColumnCell(int index, @Nullable VcsShortCommitDetails details);
+ protected abstract CommitColumnClass getCommitColumnCell(int index, @Nullable VcsShortCommitDetails details);
@NotNull
- protected abstract Class<T> getCommitColumnClass();
+ protected abstract Class<CommitColumnClass> getCommitColumnClass();
/**
* Returns the Hash of the commit displayed in the given row.