From 8f4ed824733a26b3f5aaba685ef15c1c7d333f28 Mon Sep 17 00:00:00 2001
From: Tagir Valeev
Date: Tue, 23 Apr 2019 10:39:38 +0700
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
GitOrigin-RevId: 4aa2198b0e40383875028553977a5721ba77766d
---
build/conf/nsis/idea.nsi | 5 +-
.../thumbnail/impl/ThumbnailViewUI.java | 5 +-
.../dataFlow/CustomMethodHandlers.java | 18 +-
.../completion/AllClassesGetter.java | 3 +-
.../JavaClassNameCompletionContributor.java | 1 +
.../completion/JavaCompletionUtil.java | 13 +-
.../JavaDocCompletionContributor.java | 3 +-
.../completion/JavaStaticMemberProcessor.java | 2 +-
.../LimitedAccessibleClassPreprocessor.java | 11 +-
.../completion/StaticMemberProcessor.java | 2 +-
...SimplifyStreamApiCallChainsInspection.java | 10 +-
.../FoldExpressionIntoStreamInspection.java | 7 +-
.../streamMigration/JoiningMigration.java | 19 +-
.../call/JavaCallReferenceProcessor.java | 25 +-
.../impl/search/AllClassesSearchExecutor.java | 15 +-
.../ide/hierarchy/call/DirectRecursion/A.java | 9 +
.../DirectRecursion_verification.xml | 5 +
.../hierarchy/call/IndirectRecursion/A.java | 13 +
.../IndirectRecursion_verification.xml | 8 +
.../completion/EditorTabOutTest.java | 9 +
.../ide/hierarchy/JavaCallHierarchyTest.java | 8 +
.../openapi/vfs/CompactVirtualFileSet.java | 28 +-
.../com/intellij/ui/SimpleTextAttributes.java | 13 +-
.../ide/plugins/cl/PluginClassLoader.java | 1 +
.../com/intellij/diff/DiffDialogHints.java | 21 +-
.../src/com/intellij/diff/DiffManagerEx.java | 4 +
.../com/intellij/diff/DiffRequestFactory.java | 7 +
.../intellij/diff/merge/MergeCallback.java | 60 ++
.../diff/merge/MergeRequestProducer.java | 19 +
.../com/intellij/diff/DiffManagerImpl.java | 8 +-
.../intellij/diff/DiffRequestFactoryImpl.java | 48 +-
.../intellij/diff/impl/DiffWindowBase.java | 4 +
.../intellij/diff/merge/ErrorMergeTool.java | 7 +-
.../diff/merge/MergeRequestProcessor.java | 201 +++--
.../com/intellij/diff/merge/MergeUtil.java | 29 +-
.../com/intellij/diff/merge/MergeWindow.java | 193 ++---
.../diff/merge/MessageMergeViewer.java | 59 ++
.../intellij/diff/merge/TextMergeViewer.java | 68 +-
.../diff/requests/BinaryMergeRequestImpl.java | 14 +-
.../diff/requests/TextMergeRequestImpl.java | 14 +-
.../diff/tools/external/ExternalDiffTool.java | 35 +-
.../tools/util/side/ThreesideDiffViewer.java | 8 +-
platform/dvcs-impl/src/META-INF/dvcs.xml | 1 +
.../intellij/dvcs/repo/ClonePathProvider.java | 63 ++
.../com/intellij/dvcs/ui/CloneDvcsDialog.java | 49 +-
.../ExternalSystemEventDispatcher.kt | 6 +-
.../project/manage/SourceFolderManagerImpl.kt | 5 +-
.../com/intellij/util/indexing/IdFilter.java | 15 +-
.../psi/impl/search/LowLevelSearchUtil.java | 20 +-
.../psi/search/FileNameIndexService.java | 2 +-
.../intellij/psi/search/FilenameIndex.java | 2 +-
.../properties/BraceStyleAccessor.java | 59 +-
.../properties/FieldAccessorFactory.java | 4 +-
.../properties/ForceBracesAccessor.java | 52 +-
.../properties/MagicIntegerConstAccessor.java | 43 ++
.../properties/WrappingAccessor.java | 57 +-
.../output/BuildOutputInstantReader.java | 4 +-
.../build/output/BuildOutputParser.java | 1 -
.../editorActions/TabOutScopesTracker.java | 18 +-
.../src/com/intellij/formatting/Block.java | 2 +
.../codeStyle/CommonCodeStyleSettings.java | 1 +
.../output/BuildOutputInstantReaderImpl.kt | 18 +-
.../build/output/JavacOutputParser.java | 12 +-
.../build/output/KotlincOutputParser.kt | 18 +-
.../documentation/DocumentationComponent.java | 23 +-
.../documentation/DocumentationManager.java | 4 +-
.../editorActions/BraceOrQuoteOutAction.java | 5 +-
.../TabOutScopesTrackerImpl.java | 33 +-
.../template/impl/TemplateImpl.java | 2 +-
.../extapi/psi/MetadataPsiElementBase.java | 74 --
.../intellij/extapi/psi/PsiElementBase.java | 293 --------
.../formatting/InitialInfoBuilder.java | 41 +-
.../ConfigureCodeStyleOnSelectedFragment.java | 2 +
.../ide/actions/GotoFileItemProvider.java | 2 +-
.../CreateWithTemplatesDialogPanel.java | 87 ++-
.../AbstractGotoSEContributor.java | 13 +-
.../ContributorsBasedGotoByModel.java | 11 +-
.../psi/search/FileNameIndexServiceImpl.java | 2 +-
.../proximity/PsiProximityComparator.java | 8 +-
.../BuildOutputInstantReaderImplTest.kt | 2 +-
.../execution/process/AnsiCommands.java | 87 +++
.../execution/process/AnsiEscapeDecoder.java | 224 ++----
.../execution/process/AnsiStreamingLexer.java | 162 ++++
.../execution/process/AnsiTerminalColor.java | 31 +
.../process/AnsiTerminalEmulator.java | 702 ++++++++++++++++++
.../process/ColoredOutputTypeRegistry.java | 128 +++-
.../intellij/openapi/ui/DialogWrapper.java | 43 +-
.../intellij/ui/SimpleColoredComponent.java | 17 +-
.../intellij/diagnostic/IdeErrorsDialog.java | 2 +-
.../com/intellij/ide/actions/Switcher.java | 38 +-
.../actions/ViewInplaceCommentsAction.java | 13 +
.../PluginManagerConfigurableNewLayout.java | 101 +--
.../ide/plugins/newui/PluginLogo.java | 30 +-
.../ide/plugins/newui/PluginLogoApi.java | 174 +++++
.../ide/plugins/newui/SearchQueryParser.java | 33 +-
.../ide/ui/AppearanceConfigurable.java | 6 +-
.../intellij/ide/ui/laf/LafManagerImpl.java | 16 +-
.../ide/ui/laf/darcula/darcula.properties | 10 +-
.../ide/ui/laf/intellijlaf.properties | 10 +-
.../ide/ui/laf/intellijlaf_mac.properties | 4 +
.../ide/ui/laf/intellijlaf_native.properties | 10 +-
.../diff/impl/mergeTool/MergeVersion.java | 36 -
.../impl/EditorGutterComponentImpl.java | 11 +-
.../options/newEditor/SettingsTreeView.java | 2 +-
.../com/intellij/openapi/ui/FrameWrapper.java | 37 +-
.../openapi/ui/WindowWrapperBuilder.java | 22 +-
.../openapi/vfs/newvfs/RefreshQueueImpl.java | 10 +-
.../vfs/newvfs/persistent/RefreshWorker.java | 5 +
.../header/CustomHeader.kt | 17 +-
.../intellij/ui/tree/ui/ClassicPainter.java | 5 +-
.../intellij/ui/tree/ui/CompactPainter.java | 5 +-
.../src/com/intellij/ui/tree/ui/Control.java | 5 +-
.../intellij/ui/tree/ui/DefaultControl.java | 3 +-
.../intellij/ui/tree/ui/DefaultTreeUI.java | 2 +-
.../src/META-INF/PlatformExtensions.xml | 2 +-
.../src/idea/PlatformActions.xml | 2 +
.../process/AnsiEscapeDecoderTest.java | 183 +++--
.../editor/impl/IterationStateTest.java | 31 +-
.../editor/impl/softwrap/SoftWrapTest.java | 4 +
...apApplianceOnDocumentModificationTest.java | 58 +-
.../ui/tree/ui/TreeControlPainterTest.java | 3 +-
.../concurrency/BackgroundTaskQueueTest.java | 2 +-
.../testFramework/LightProjectDescriptor.java | 17 +-
.../util/resources/misc/registry.properties | 10 +-
.../util/containers/ContainerUtil.java | 22 +
.../containers/FilteredTraverserBase.java | 9 +-
.../util/src/com/intellij/util/io/IOUtil.java | 13 +-
.../util/src/com/intellij/util/ui/JBUI.java | 25 +
.../src/com/intellij/vcsUtil/VcsUtil.java | 16 +
.../com/intellij/openapi/vcs/ZipAndQueue.java | 19 +-
.../DefaultPatchBaseVersionProvider.java | 28 +-
.../patch/PatchDiffRequestFactory.java | 6 +-
.../patch/tool/ApplyPatchMergeRequest.java | 14 +-
.../ui/ChangesBrowserNodeRenderer.java | 2 +-
.../changes/ui/ChangesViewContentManager.java | 87 ++-
.../vcs/merge/MergeConflictsTreeTable.kt | 48 ++
.../vcs/merge/MultipleFileMergeDialog.kt | 50 +-
.../StringEqualsCharSequenceInspection.java | 19 +-
...ngBufferReplaceableByStringInspection.java | 3 +-
.../application/CvsEntriesManager.java | 10 +-
...CvsStorageSupportingDeletionComponent.java | 2 +-
.../git4idea/resources/META-INF/plugin.xml | 7 +
.../GitConflictsToolWindowManager.java | 69 ++
.../git4idea/conflicts/GitConflictsView.kt | 270 +++++++
.../git4idea/conflicts/GitMergeHandler.java | 197 +++++
.../conflicts/MergeConflictResolveUtil.kt | 139 ++++
.../src/git4idea/merge/GitMergeProvider.java | 103 +--
.../src/git4idea/merge/GitMergeUtil.java | 68 +-
.../src/git4idea/repo/GitConflict.java | 62 ++
.../src/git4idea/repo/GitConflictsHolder.java | 69 ++
.../src/git4idea/repo/GitRepository.java | 3 +
.../src/git4idea/repo/GitRepositoryImpl.java | 16 +-
.../git4idea/status/GitChangeProvider.java | 4 +
.../git4idea/status/GitChangesCollector.java | 76 +-
.../git4idea/test/MockGitRepository.java | 6 +
.../META-INF/gradle-groovy-integration.xml | 3 +-
.../META-INF/gradle-java-integration.xml | 2 -
.../GradleJavaOutputParserProvider.java | 29 -
.../resolve/GradleDomainObjectProperty.kt | 10 +
.../resolve/GradleExtensionsContributor.kt | 77 +-
.../resolve/GradleIdeaSettingsContributor.kt | 8 +-
.../service/resolve/GradleMiscContributor.kt | 6 +-
.../GradleNamedDomainCollectionContributor.kt | 58 ++
.../GradleNonCodeMembersContributor.kt | 59 +-
.../GradleProjectExtensionContributor.kt | 66 ++
.../GradleUnresolvedReferenceFilter.java | 31 +-
...medDomainObjectCollectionTypeEnhancer.java | 106 ---
.../dsl/GradleDistributionsTest.groovy | 62 +-
.../testSources/dsl/GradleTasksTest.groovy | 22 +-
.../output/GradleBuildScriptErrorParser.kt | 2 +-
.../output/GradleOutputDispatcherFactory.kt | 27 +-
.../output/GradleOutputParserProvider.java | 15 +-
.../build/output/GradleSyncOutputParser.java | 5 +-
.../importing/GradleFoldersImportingTest.java | 29 +
.../ExternalTestsModelBuilderImpl.groovy | 8 +-
.../builder/JsonBuilderContributor.java | 12 +-
.../builder/JsonDelegateContributor.java | 8 +-
.../StreamingJsonBuilderContributor.java | 6 +-
...MarkupBuilderNonCodeMemberContributor.java | 14 +-
.../lang/psi/impl/GroovyPsiManager.java | 4 +-
.../lang/psi/impl/InferenceContext.java | 4 +-
.../groovy/lang/psi/impl/PartialContext.kt | 4 +-
.../lang/psi/impl/TopInferenceContext.kt | 4 +-
.../blocks/GrClosableBlockImpl.java | 5 +-
.../statements/expressions/ClassUtil.java | 6 +-
.../GrAssignmentExpressionImpl.java | 2 +-
.../typedef/members/GrMethodBaseImpl.java | 2 +-
.../synthetic/ClosureSyntheticParameter.java | 19 +-
.../lang/resolve/api/SimpleGroovyProperty.kt | 11 +
.../delegatesTo/DefaultDelegatesToProvider.kt | 6 +-
.../resolve/delegatesTo/grDelegatesToUtil.kt | 10 +-
.../LogbackDelegateMemberContributor.kt | 6 +-
.../completion/GrMainCompletionProvider.java | 2 +-
.../groovy/GroovyGotoDeclarationTest.groovy | 4 +-
.../GroovyLightProjectDescriptor.groovy | 38 -
.../jetbrains/plugins/groovy/SetupRule.groovy | 20 +-
.../groovy/builder/JsonBuilderTest.groovy | 21 +-
.../builder/StreamingJsonBuilderTest.groovy | 20 +-
.../GroovyMoveLeftRightHandlerTest.groovy | 6 +-
...oovyInlayParameterHintsProviderTest.groovy | 4 +-
...oovyIdenticalBranchesInspectionTest.groovy | 20 +-
...nnecessaryDefModifierInspectionTest.groovy | 20 +-
...cessaryPublicModifierInspectionTest.groovy | 23 +-
...rUnnecessarySemicolonInspectionTest.groovy | 6 +-
...nusedDefaultParameterInspectionTest.groovy | 21 +-
...derTransformationCompletionTestBase.groovy | 20 +-
.../MiscBuilderTransformationTest.groovy | 20 +-
.../ext/newify/NewifyResolveTest.groovy | 6 +-
.../ext/newify/NewifySupportTest.groovy | 6 +-
.../ext/spock/SpockLineMarkersTest.groovy | 20 +-
.../CreateConstantFromJavaUsageTest.groovy | 7 +-
.../fixes/GrLoosePrecisionFixTest.groovy | 6 +-
.../fixes/GrMultipleAssignmentTest.groovy | 6 +-
.../groovy/fixes/GrSpreadArgumentTest.groovy | 20 +-
.../geb/AbstractGebLightTestCase.groovy | 64 --
.../plugins/groovy/geb/GebTestsTest.groovy | 33 +-
.../groovy/ide/GroovyRunLineMarkerTest.groovy | 6 +-
.../inspections/GrChangeToMethodTest.groovy | 35 +-
.../inspections/GrChangeToOperatorTest.groovy | 6 +-
.../GrMethodMayBeStaticTest.groovy | 20 +-
.../highlighting/GrClosureParamsTest.groovy | 4 +-
.../GrHighlightingAttributesTest.groovy | 6 +-
.../GrLatestHighlightingTest.groovy | 6 +-
.../GroovyHighlightUsagesTest.groovy | 4 +-
.../groovy/lang/psi/ModifiersTest.groovy | 8 +-
.../FromAbstractTypeMethodsTest.groovy | 20 +-
.../resolve/ConstantExpressionTest.groovy | 6 +-
.../lang/resolve/CustomMapPropertyTest.groovy | 4 +-
.../resolve/DelegatesToSupportTest.groovy | 20 +-
.../resolve/GrImportContributorTest.groovy | 4 +-
.../lang/resolve/GrNumericLUBTypeTest.groovy | 20 +-
.../resolve/GroovyTraitCoercionTest.groovy | 20 +-
.../lang/resolve/MapPropertyTest.groovy | 6 +-
.../NavigateDelegatedClsMethodsTest.groovy | 39 +-
.../lang/resolve/NumberMathTypingTest.groovy | 4 +-
.../lang/resolve/ResolveAttributeTest.groovy | 6 +-
.../lang/resolve/ResolveClassInNewTest.groovy | 6 +-
.../resolve/ResolveFieldVsAccessorTest.groovy | 6 +-
.../resolve/ResolveIndexPropertyTest.groovy | 6 +-
.../ResolveOperatorAssignmentTest.groovy | 20 +-
...ResolvePropertyViaAliasedImportTest.groovy | 6 +-
.../ResolveWithDelegatesToOnLambdaTest.groovy | 4 +-
.../resolve/ResolveWithDelegatesToTest.groovy | 6 +-
.../lang/resolve/SelfTypeSupportTest.groovy | 20 +-
.../dgm/ResolveDGMMethodLatestTest.groovy | 20 +-
.../dgm/ResolveExtensionMethodTest.groovy | 4 +-
.../modifiers/GrVisibilityTestBase.groovy | 20 +-
.../rename/InplaceRenameTest.groovy | 20 +-
...BaseScriptTransformationSupportTest.groovy | 20 +-
...rAutoCloneTransformationSupportTest.groovy | 4 +-
.../GrNoTransformationsTest.groovy | 8 +-
.../GrTransformationsTest.groovy | 6 +-
.../SynchronizedTransformationTest.groovy | 20 +-
.../ImmutableTransformationSupportTest.groovy | 6 +-
.../IndexedPropertyTest.groovy | 20 +-
.../listenerList/ListenerListTest.groovy | 20 +-
.../SingletonConstructorInspectionTest.groovy | 20 +-
.../SingletonNewInstanceInspectionTest.groovy | 20 +-
.../SingletonTransformationSupportTest.groovy | 20 +-
.../plugins/groovy/util/ExpressionTest.java | 54 ++
.../groovy/util/ReferenceExpressionTest.java | 16 -
.../mockGeb/geb-core-0.7.1-sources.jar | Bin 84962 -> 0 bytes
.../testdata/mockGeb/geb-core-0.7.1.jar | Bin 221593 -> 0 bytes
.../testdata/mockGeb/geb-junit4-0.7.0.jar | Bin 7700 -> 0 bytes
.../testdata/mockGeb/geb-spock-0.7.1.jar | Bin 9305 -> 0 bytes
.../testdata/mockGeb/geb-testng-0.7.2.jar | Bin 8010 -> 0 bytes
.../output/MavenImportOutputParser.java | 6 +-
.../output/MavenBuildToolLogTestUtils.java | 2 +-
.../editor/ResourceBundleEditor.java | 15 +-
.../pydev/_pydev_bundle/pydev_monkey.py | 67 +-
.../jetbrains/python/formatter/PyBlock.java | 2 +-
.../python/sdk/PythonSdkUpdater.java | 26 +-
.../tox/PyToxConfigurationProducer.java | 4 +-
.../tox/PyToxConfigurationSettings.form | 2 +-
.../testing/tox/PyToxConfigurationType.java | 2 +-
.../debug/test_executable_script_debug.py | 7 +
.../test_executable_script_debug_helper.py | 5 +
.../env/python/PythonDebuggerTest.java | 24 +
.../src/com/jetbrains/python/tools/Utils.kt | 2 +-
.../src/org/jetbrains/index/stubs/SdkUtils.kt | 3 +-
280 files changed, 4726 insertions(+), 3079 deletions(-)
create mode 100644 java/java-tests/testData/ide/hierarchy/call/DirectRecursion/A.java
create mode 100644 java/java-tests/testData/ide/hierarchy/call/DirectRecursion/DirectRecursion_verification.xml
create mode 100644 java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/A.java
create mode 100644 java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/IndirectRecursion_verification.xml
create mode 100644 platform/diff-api/src/com/intellij/diff/merge/MergeCallback.java
create mode 100644 platform/diff-api/src/com/intellij/diff/merge/MergeRequestProducer.java
create mode 100644 platform/diff-impl/src/com/intellij/diff/merge/MessageMergeViewer.java
create mode 100644 platform/dvcs-impl/src/com/intellij/dvcs/repo/ClonePathProvider.java
create mode 100644 platform/lang-api/src/com/intellij/application/options/codeStyle/properties/MagicIntegerConstAccessor.java
rename {java/compiler/impl => platform/lang-impl}/src/com/intellij/build/output/JavacOutputParser.java (90%)
rename {java/compiler/impl => platform/lang-impl}/src/com/intellij/build/output/KotlincOutputParser.kt (85%)
delete mode 100644 platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiElementBase.java
delete mode 100644 platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java
create mode 100644 platform/platform-api/src/com/intellij/execution/process/AnsiCommands.java
create mode 100644 platform/platform-api/src/com/intellij/execution/process/AnsiStreamingLexer.java
create mode 100644 platform/platform-api/src/com/intellij/execution/process/AnsiTerminalColor.java
create mode 100644 platform/platform-api/src/com/intellij/execution/process/AnsiTerminalEmulator.java
create mode 100644 platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogoApi.java
create mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MergeConflictsTreeTable.kt
create mode 100644 plugins/git4idea/src/git4idea/conflicts/GitConflictsToolWindowManager.java
create mode 100644 plugins/git4idea/src/git4idea/conflicts/GitConflictsView.kt
create mode 100644 plugins/git4idea/src/git4idea/conflicts/GitMergeHandler.java
create mode 100644 plugins/git4idea/src/git4idea/conflicts/MergeConflictResolveUtil.kt
create mode 100644 plugins/git4idea/src/git4idea/repo/GitConflict.java
create mode 100644 plugins/git4idea/src/git4idea/repo/GitConflictsHolder.java
delete mode 100644 plugins/gradle/java/src/execution/build/output/GradleJavaOutputParserProvider.java
create mode 100644 plugins/gradle/java/src/service/resolve/GradleDomainObjectProperty.kt
create mode 100644 plugins/gradle/java/src/service/resolve/GradleNamedDomainCollectionContributor.kt
create mode 100644 plugins/gradle/java/src/service/resolve/GradleProjectExtensionContributor.kt
delete mode 100644 plugins/gradle/java/src/service/resolve/NamedDomainObjectCollectionTypeEnhancer.java
create mode 100644 plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/api/SimpleGroovyProperty.kt
delete mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyLightProjectDescriptor.groovy
delete mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/geb/AbstractGebLightTestCase.groovy
create mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/util/ExpressionTest.java
delete mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/util/ReferenceExpressionTest.java
delete mode 100644 plugins/groovy/testdata/mockGeb/geb-core-0.7.1-sources.jar
delete mode 100644 plugins/groovy/testdata/mockGeb/geb-core-0.7.1.jar
delete mode 100644 plugins/groovy/testdata/mockGeb/geb-junit4-0.7.0.jar
delete mode 100644 plugins/groovy/testdata/mockGeb/geb-spock-0.7.1.jar
delete mode 100644 plugins/groovy/testdata/mockGeb/geb-testng-0.7.2.jar
create mode 100644 python/testData/debug/test_executable_script_debug.py
create mode 100644 python/testData/debug/test_executable_script_debug_helper.py
diff --git a/build/conf/nsis/idea.nsi b/build/conf/nsis/idea.nsi
index ba2d6c266fd6..663c28d15e59 100644
--- a/build/conf/nsis/idea.nsi
+++ b/build/conf/nsis/idea.nsi
@@ -1881,8 +1881,11 @@ skip_delete_settings:
!insertmacro INSTALLOPTIONS_READ $R3 "DeleteSettings.ini" "Field 7" "State"
StrCmp $R3 1 "" skip_delete_tools
SetShellVarContext current
- IfFileExists "$LOCALAPPDATA\${MANUFACTURER}\BuildTools\*.*" 0 continue_uninstall
+ IfFileExists "$LOCALAPPDATA\${MANUFACTURER}\BuildTools\*.*" 0 delete_downloaded_jdk8
RmDir /r "$LOCALAPPDATA\${MANUFACTURER}\BuildTools"
+delete_downloaded_jdk8:
+ IfFileExists "$LOCALAPPDATA\${MANUFACTURER}\jdk8\*.*" 0 continue_uninstall
+ RmDir /r "$LOCALAPPDATA\${MANUFACTURER}\jdk8"
continue_uninstall:
StrCmp $baseRegKey "HKLM" 0 skip_delete_tools
diff --git a/images/src/org/intellij/images/thumbnail/impl/ThumbnailViewUI.java b/images/src/org/intellij/images/thumbnail/impl/ThumbnailViewUI.java
index dde58f0d1e66..b0293d4c918a 100644
--- a/images/src/org/intellij/images/thumbnail/impl/ThumbnailViewUI.java
+++ b/images/src/org/intellij/images/thumbnail/impl/ThumbnailViewUI.java
@@ -68,7 +68,6 @@ import java.util.List;
import java.util.*;
final class ThumbnailViewUI extends JPanel implements DataProvider, Disposable {
- private final VirtualFileListener vfsListener = new VFSListener();
private final OptionsChangeListener optionsListener = new OptionsChangeListener();
private static final Navigatable[] EMPTY_NAVIGATABLE_ARRAY = new Navigatable[]{};
@@ -107,7 +106,7 @@ final class ThumbnailViewUI extends JPanel implements DataProvider, Disposable {
cellRenderer = new ThumbnailListCellRenderer();
ImageComponent imageComponent = cellRenderer.getImageComponent();
- VirtualFileManager.getInstance().addVirtualFileListener(vfsListener);
+ VirtualFileManager.getInstance().addVirtualFileListener(new VFSListener(), this);
Options options = OptionsManager.getInstance().getOptions();
EditorOptions editorOptions = options.getEditorOptions();
@@ -624,8 +623,6 @@ final class ThumbnailViewUI extends JPanel implements DataProvider, Disposable {
Options options = OptionsManager.getInstance().getOptions();
options.removePropertyChangeListener(optionsListener);
- VirtualFileManager.getInstance().removeVirtualFileListener(vfsListener);
-
list = null;
cellRenderer = null;
tagsPanel = null;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CustomMethodHandlers.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CustomMethodHandlers.java
index 6065d07a76a3..75ccbe8f3168 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CustomMethodHandlers.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CustomMethodHandlers.java
@@ -1,18 +1,4 @@
-/*
- * Copyright 2000-2017 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.
- */
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet;
@@ -163,7 +149,7 @@ class CustomMethodHandlers {
if (TypeUtils.isJavaLangObject(type)) {
return Object.class;
}
- if (TypeUtils.typeEquals("java.lang.CharSequence", type)) {
+ if (TypeUtils.typeEquals(JAVA_LANG_CHARSEQUENCE, type)) {
return CharSequence.class;
}
if (PsiType.INT.equals(type)) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
index dfbd37f7650d..904bcf8f80b5 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
@@ -119,7 +119,7 @@ public class AllClassesGetter {
final Project project = context.getProject();
final GlobalSearchScope scope = filterByScope ? context.getContainingFile().getResolveScope() : GlobalSearchScope.allScope(project);
- processJavaClasses(prefixMatcher, project, scope, new LimitedAccessibleClassPreprocessor(parameters, filterByScope, consumer));
+ processJavaClasses(prefixMatcher, project, scope, new LimitedAccessibleClassPreprocessor(parameters, filterByScope, c->{consumer.consume(c); return true;}));
}
public static void processJavaClasses(@NotNull final PrefixMatcher prefixMatcher,
@@ -131,6 +131,7 @@ public class AllClassesGetter {
if (prefixMatcher.prefixMatches(s)) {
names.add(s);
}
+ return true;
});
LinkedHashSet sorted = CompletionUtil.sortMatching(prefixMatcher, names);
AllClassesSearchExecutor.processClassesByNames(project, scope, sorted, processor);
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java
index 1166a3b4c504..b26f2f559eeb 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java
@@ -106,6 +106,7 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
JavaPsiClassReferenceElement item = AllClassesGetter.createLookupItem(anno, JAVA_CLASS_INSERT_HANDLER);
item.addLookupStrings(getClassNameWithContainers(anno));
consumer.consume(item);
+ return true;
});
for (String name : CompletionUtil.sortMatching(matcher, annoMap.keySet())) {
if (!ContainerUtil.process(annoMap.get(name), processor)) break;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
index 7440dc967e4a..72b4420df83b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
@@ -7,6 +7,7 @@ import com.intellij.codeInsight.completion.scope.CompletionElement;
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
import com.intellij.codeInsight.daemon.impl.analysis.LambdaHighlightingUtil;
+import com.intellij.codeInsight.editorActions.TabOutScopesTracker;
import com.intellij.codeInsight.guess.GuessManager;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInspection.java15api.Java15APIUsageInspection;
@@ -98,7 +99,7 @@ public class JavaCompletionUtil {
JavaMemberNameCompletionContributor.completeVariableNameForRefactoring(project, set, camelHumpMatcher, varType, varKind, true, false);
}
- public static void putAllMethods(LookupElement item, List methods) {
+ public static void putAllMethods(LookupElement item, List extends PsiMethod> methods) {
item.putUserData(ALL_METHODS_ATTRIBUTE, ContainerUtil.map(methods, method -> SmartPointerManager.getInstance(method.getProject()).createSmartPsiElementPointer(method)));
}
@@ -827,7 +828,15 @@ public class JavaCompletionUtil {
}
}
- toInsert.processTail(context.getEditor(), context.getTailOffset());
+ Editor editor = context.getEditor();
+ int tailOffset = context.getTailOffset();
+ int afterTailOffset = toInsert.processTail(editor, tailOffset);
+ int caretOffset = editor.getCaretModel().getOffset();
+ if (afterTailOffset > tailOffset &&
+ tailOffset > caretOffset &&
+ TabOutScopesTracker.getInstance().removeScopeEndingAt(editor, caretOffset) > 0) {
+ TabOutScopesTracker.getInstance().registerEmptyScope(editor, caretOffset, afterTailOffset - caretOffset);
+ }
return true;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
index bc1f47f82d08..10da8ed151c2 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
@@ -223,7 +223,8 @@ public class JavaDocCompletionContributor extends CompletionContributor {
for (LookupElement element : completeJavadocReference(ref.getElement(), ref)) {
result.addElement(LookupElementDecorator.withInsertHandler(element, wrapIntoLinkTag((context, item) -> element.handleInsert(context))));
}
- } else if (matcher.getPrefix().length() > 0) {
+ }
+ else if (matcher.getPrefix().length() > 0) {
InsertHandler handler = wrapIntoLinkTag(JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER);
AllClassesGetter.processJavaClasses(parameters, matcher, parameters.getInvocationCount() == 1, psiClass ->
result.addElement(AllClassesGetter.createLookupItem(psiClass, handler)));
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaStaticMemberProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaStaticMemberProcessor.java
index 37120f20cac2..ccc4f235f057 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaStaticMemberProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaStaticMemberProcessor.java
@@ -69,7 +69,7 @@ public class JavaStaticMemberProcessor extends StaticMemberProcessor {
}
@Override
- protected LookupElement createLookupElement(@NotNull List overloads,
+ protected LookupElement createLookupElement(@NotNull List extends PsiMethod> overloads,
@NotNull PsiClass containingClass,
boolean shouldImport) {
shouldImport |= myOriginalPosition != null && PsiTreeUtil.isAncestor(containingClass, myOriginalPosition, false);
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/LimitedAccessibleClassPreprocessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/LimitedAccessibleClassPreprocessor.java
index 98f18602e73a..b95c63e4384b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/LimitedAccessibleClassPreprocessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/LimitedAccessibleClassPreprocessor.java
@@ -20,7 +20,6 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
-import com.intellij.util.Consumer;
import com.intellij.util.Processor;
import gnu.trove.THashSet;
@@ -34,18 +33,18 @@ class LimitedAccessibleClassPreprocessor implements Processor {
private final PsiElement myContext;
private final CompletionParameters myParameters;
private final boolean myFilterByScope;
- private final Consumer super PsiClass> myConsumer;
+ private final Processor super PsiClass> myProcessor;
private final int myLimit = Registry.intValue("ide.completion.variant.limit");
private int myCount;
private final Set myQNames = new THashSet<>();
private final boolean myPkgContext;
private final String myPackagePrefix;
- LimitedAccessibleClassPreprocessor(CompletionParameters parameters, boolean filterByScope, Consumer super PsiClass> consumer) {
+ LimitedAccessibleClassPreprocessor(CompletionParameters parameters, boolean filterByScope, Processor super PsiClass> processor) {
myContext = parameters.getPosition();
myParameters = parameters;
myFilterByScope = filterByScope;
- myConsumer = consumer;
+ myProcessor = processor;
myPkgContext = JavaCompletionUtil.inSomePackage(myContext);
myPackagePrefix = getPackagePrefix(myContext, myParameters.getOffset());
}
@@ -70,7 +69,7 @@ class LimitedAccessibleClassPreprocessor implements Processor {
return true;
}
String name = psiClass.getName();
- if (name != null && name.length() > 0 && Character.isLowerCase(name.charAt(0)) &&
+ if (name != null && !name.isEmpty() && Character.isLowerCase(name.charAt(0)) &&
!Registry.is("ide.completion.show.lower.case.classes")) {
return true;
}
@@ -83,7 +82,7 @@ class LimitedAccessibleClassPreprocessor implements Processor {
LOG.debug("Processing class " + qName);
}
if (qName != null && qName.startsWith(myPackagePrefix) && myQNames.add(qName)) {
- myConsumer.consume(psiClass);
+ if (!myProcessor.process(psiClass)) return false;
if (++myCount > myLimit) {
LOG.debug("Limit reached");
return false;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java
index 69da72b66e4f..c6427736dfa3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java
@@ -147,5 +147,5 @@ public abstract class StaticMemberProcessor {
@Nullable
protected abstract LookupElement createLookupElement(@NotNull PsiMember member, @NotNull PsiClass containingClass, boolean shouldImport);
- protected abstract LookupElement createLookupElement(@NotNull List overloads, @NotNull PsiClass containingClass, boolean shouldImport);
+ protected abstract LookupElement createLookupElement(@NotNull List extends PsiMethod> overloads, @NotNull PsiClass containingClass, boolean shouldImport);
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java b/java/java-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java
index b92ef68a9be0..19e27c6dcdbb 100644
--- a/java/java-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection;
import com.intellij.codeInsight.ExpressionUtil;
@@ -1773,7 +1773,7 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal
static final CallMatcher COLLECTOR_JOINING = staticCall(JAVA_UTIL_STREAM_COLLECTORS, "joining")
.parameterCount(0);
static final CallMatcher COLLECTOR_JOINING_DELIMITER = staticCall(JAVA_UTIL_STREAM_COLLECTORS, "joining")
- .parameterTypes("java.lang.CharSequence");
+ .parameterTypes(JAVA_LANG_CHARSEQUENCE);
@Override
public String getName() {
@@ -1826,7 +1826,7 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal
if (ARRAYS_STREAM.matches(qualifier) ||
(COLLECTION_STREAM.matches(qualifier) && ExpressionUtils.getEffectiveQualifier(qualifier.getMethodExpression()) != null)) {
PsiType elementType = StreamApiUtil.getStreamElementType(qualifier.getType());
- if (InheritanceUtil.isInheritor(elementType, "java.lang.CharSequence")) {
+ if (InheritanceUtil.isInheritor(elementType, JAVA_LANG_CHARSEQUENCE)) {
return new JoiningStringsFix();
}
}
@@ -1911,11 +1911,11 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal
if (PsiUtil.skipParenthesizedExprDown(argumentExpressions[1]) != call) return null;
PsiExpression delimiter = argumentExpressions[0];
if (delimiter == null) return null;
- if(!InheritanceUtil.isInheritor(delimiter.getType(), "java.lang.CharSequence")) return null;
+ if(!InheritanceUtil.isInheritor(delimiter.getType(), JAVA_LANG_CHARSEQUENCE)) return null;
PsiMethodCallExpression stream = getQualifierMethodCall(call);
if (stream == null) return null;
PsiType elementType = StreamApiUtil.getStreamElementType(stream.getType());
- if (!InheritanceUtil.isInheritor(elementType, "java.lang.CharSequence")) return null;
+ if (!InheritanceUtil.isInheritor(elementType, JAVA_LANG_CHARSEQUENCE)) return null;
return new Context(maybeJoinCall, delimiter, argument);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/streamMigration/FoldExpressionIntoStreamInspection.java b/java/java-impl/src/com/intellij/codeInspection/streamMigration/FoldExpressionIntoStreamInspection.java
index b608a3c0a07a..0a2f408f6c50 100644
--- a/java/java-impl/src/com/intellij/codeInspection/streamMigration/FoldExpressionIntoStreamInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/streamMigration/FoldExpressionIntoStreamInspection.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.streamMigration;
import com.intellij.codeInspection.*;
@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Objects;
import static com.intellij.codeInsight.intention.impl.StreamRefactoringUtil.getMapOperationName;
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_CHARSEQUENCE;
import static com.intellij.util.ObjectUtils.tryCast;
public class FoldExpressionIntoStreamInspection extends AbstractBaseJavaLocalInspectionTool {
@@ -137,7 +138,7 @@ public class FoldExpressionIntoStreamInspection extends AbstractBaseJavaLocalIns
PsiExpression[] operands = polyadicExpression.getOperands();
String mapToString;
PsiType operandType = operands[0].getType();
- if (!InheritanceUtil.isInheritor(operandType, "java.lang.CharSequence")) {
+ if (!InheritanceUtil.isInheritor(operandType, JAVA_LANG_CHARSEQUENCE)) {
if (!StreamApiUtil.isSupportedStreamElement(operandType)) return null;
mapToString = "."+getMapOperationName(operandType, type)+"(String::valueOf)";
} else {
@@ -150,7 +151,7 @@ public class FoldExpressionIntoStreamInspection extends AbstractBaseJavaLocalIns
.pairMap(EquivalenceChecker.getCanonicalPsiEquivalence()::expressionsAreEquivalent)
.allMatch(Boolean.TRUE::equals)) {
delimiter = operands[1];
- if (!InheritanceUtil.isInheritor(delimiter.getType(), "java.lang.CharSequence") &&
+ if (!InheritanceUtil.isInheritor(delimiter.getType(), JAVA_LANG_CHARSEQUENCE) &&
!(delimiter instanceof PsiLiteralExpression && PsiType.CHAR.equals(delimiter.getType()))) {
return null;
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/streamMigration/JoiningMigration.java b/java/java-impl/src/com/intellij/codeInspection/streamMigration/JoiningMigration.java
index 22e755dea893..71f788d4f6fa 100644
--- a/java/java-impl/src/com/intellij/codeInspection/streamMigration/JoiningMigration.java
+++ b/java/java-impl/src/com/intellij/codeInspection/streamMigration/JoiningMigration.java
@@ -1,18 +1,4 @@
-/*
- * Copyright 2000-2017 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.
- */
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.streamMigration;
@@ -41,6 +27,7 @@ import java.util.function.Predicate;
import static com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil.isEffectivelyFinal;
import static com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.isCallOf;
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_CHARSEQUENCE;
import static com.intellij.util.ObjectUtils.tryCast;
import static com.siyeh.ig.psiutils.ControlFlowUtils.getInitializerUsageStatus;
import static com.siyeh.ig.psiutils.ExpressionUtils.resolveLocalVariable;
@@ -330,7 +317,7 @@ public class JoiningMigration extends BaseStreamApiMigration {
}
}
}
- if (!InheritanceUtil.isInheritor(type, "java.lang.CharSequence")) {
+ if (!InheritanceUtil.isInheritor(type, JAVA_LANG_CHARSEQUENCE)) {
if (!neighborIsString || (type instanceof PsiArrayType && ((PsiArrayType)type).getComponentType().equals(PsiType.CHAR))) {
PsiLiteralExpression literalExpression = tryCast(expression, PsiLiteralExpression.class);
if (literalExpression != null) {
diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/call/JavaCallReferenceProcessor.java b/java/java-impl/src/com/intellij/ide/hierarchy/call/JavaCallReferenceProcessor.java
index 808aeb4720b7..c3d7b24ac553 100644
--- a/java/java-impl/src/com/intellij/ide/hierarchy/call/JavaCallReferenceProcessor.java
+++ b/java/java-impl/src/com/intellij/ide/hierarchy/call/JavaCallReferenceProcessor.java
@@ -84,11 +84,13 @@ public class JavaCallReferenceProcessor implements CallReferenceProcessor {
final PsiElement element = reference.getElement();
final PsiMember key = CallHierarchyNodeDescriptor.getEnclosingElement(element);
+ CallHierarchyNodeDescriptor parentDescriptor = (CallHierarchyNodeDescriptor) data.getNodeDescriptor();
+ if (isRecursiveNode(method, parentDescriptor)) return false;
synchronized (methodToDescriptorMap) {
CallHierarchyNodeDescriptor d = (CallHierarchyNodeDescriptor)methodToDescriptorMap.get(key);
if (d == null) {
- d = new CallHierarchyNodeDescriptor(myProject, (CallHierarchyNodeDescriptor)data.getNodeDescriptor(), element, false, true);
+ d = new CallHierarchyNodeDescriptor(myProject, parentDescriptor, element, false, true);
methodToDescriptorMap.put(key, d);
}
else if (!d.hasReference(reference)) {
@@ -98,4 +100,25 @@ public class JavaCallReferenceProcessor implements CallReferenceProcessor {
}
return false;
}
+
+ private static boolean isRecursiveNode(@NotNull PsiMethod method, @NotNull CallHierarchyNodeDescriptor parentDescriptor) {
+ // detect recursion
+ // the current call-site calls *method*
+ // Thus, we already have a node that represents *method*
+ // Check whether we have any other node along the parent-chain that represents that same method
+
+ NodeDescriptor ancestorDescriptor = parentDescriptor;
+ // Start check on grandparent
+ while ((ancestorDescriptor = ancestorDescriptor.getParentDescriptor()) != null) {
+ if (ancestorDescriptor instanceof CallHierarchyNodeDescriptor) {
+ PsiMember ancestorCallSite = ((CallHierarchyNodeDescriptor)ancestorDescriptor).getEnclosingElement();
+ if (ancestorCallSite == method) {
+ // We have at least two occurrences in the parent chain of method already
+ // Don't search any deeper
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java
index ebd764b92cb4..b852305487a4 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java
@@ -17,7 +17,6 @@ import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.AllClassesSearch;
-import com.intellij.util.Consumer;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import com.intellij.util.indexing.IdFilter;
@@ -50,6 +49,7 @@ public class AllClassesSearchExecutor implements QueryExecutor sorted = new ArrayList<>(names);
@@ -75,18 +75,15 @@ public class AllClassesSearchExecutor implements QueryExecutor consumer) {
- DumbService.getInstance(project).runReadActionInSmartMode((Computable)() -> {
+ public static boolean processClassNames(final Project project, final GlobalSearchScope scope, final Processor super String> processor) {
+ boolean success = DumbService.getInstance(project).runReadActionInSmartMode((Computable)() ->
PsiShortNamesCache.getInstance(project).processAllClassNames(s -> {
ProgressManager.checkCanceled();
- consumer.consume(s);
- return true;
- }, scope, IdFilter.getProjectIdFilter(project, true));
- return null;
- });
+ return processor.process(s);
+ }, scope, IdFilter.getProjectIdFilter(project, true)));
ProgressManager.checkCanceled();
- return project;
+ return success;
}
private static boolean processScopeRootForAllClasses(@NotNull final PsiElement scopeRoot, @NotNull final Processor super PsiClass> processor) {
diff --git a/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/A.java b/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/A.java
new file mode 100644
index 000000000000..b2f5460a32fc
--- /dev/null
+++ b/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/A.java
@@ -0,0 +1,9 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+class A {
+ public static void main(String[] args) {
+ recursive();
+ }
+ public static void recursive() {
+ recursive();
+ }
+}
diff --git a/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/DirectRecursion_verification.xml b/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/DirectRecursion_verification.xml
new file mode 100644
index 000000000000..d8101f0674d8
--- /dev/null
+++ b/java/java-tests/testData/ide/hierarchy/call/DirectRecursion/DirectRecursion_verification.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/A.java b/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/A.java
new file mode 100644
index 000000000000..255c46fe530a
--- /dev/null
+++ b/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/A.java
@@ -0,0 +1,13 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+class A {
+ public static void main(String[] args) {
+ recursive1();
+ }
+ public static void recursive1() {
+ recursive2();
+ }
+
+ public static void recursive2() {
+ recursive1();
+ }
+}
diff --git a/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/IndirectRecursion_verification.xml b/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/IndirectRecursion_verification.xml
new file mode 100644
index 000000000000..cc117a25fd0e
--- /dev/null
+++ b/java/java-tests/testData/ide/hierarchy/call/IndirectRecursion/IndirectRecursion_verification.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/EditorTabOutTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/EditorTabOutTest.java
index 99656ecd19c1..4d29cb4673e5 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/EditorTabOutTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/EditorTabOutTest.java
@@ -90,6 +90,15 @@ public class EditorTabOutTest extends AbstractParameterInfoTestCase {
"}");
}
+ public void testSemicolon() {
+ configureJava("class C { void m() { System.exi } }");
+ complete("exit");
+ checkResult("class C { void m() { System.exit(); } }");
+ type('1');
+ tabOut();
+ checkResult("class C { void m() { System.exit(1); } }");
+ }
+
private void tabOut() {
myFixture.performEditorAction(IdeActions.ACTION_BRACE_OR_QUOTE_OUT);
}
diff --git a/java/java-tests/testSrc/com/intellij/java/ide/hierarchy/JavaCallHierarchyTest.java b/java/java-tests/testSrc/com/intellij/java/ide/hierarchy/JavaCallHierarchyTest.java
index 47bc9e6edf88..9ef56c77ff69 100644
--- a/java/java-tests/testSrc/com/intellij/java/ide/hierarchy/JavaCallHierarchyTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/ide/hierarchy/JavaCallHierarchyTest.java
@@ -58,6 +58,14 @@ public class JavaCallHierarchyTest extends HierarchyViewTestBase {
doJavaCallTypeHierarchyTest("B", "xyzzy", "B.java", "D.java", "A.java");
}
+ public void testDirectRecursion() throws Exception {
+ doJavaCallTypeHierarchyTest("A", "recursive", "A.java");
+ }
+
+ public void testIndirectRecursion() throws Exception {
+ doJavaCallTypeHierarchyTest("A", "recursive2", "A.java");
+ }
+
public void testIdeaDev41005_Inheritance() throws Exception {
doJavaCallTypeHierarchyTest("D", "xyzzy", "B.java", "D.java", "A.java", "C.java");
}
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/CompactVirtualFileSet.java b/platform/core-api/src/com/intellij/openapi/vfs/CompactVirtualFileSet.java
index 262a0f117277..cb70612a8136 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/CompactVirtualFileSet.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/CompactVirtualFileSet.java
@@ -5,12 +5,9 @@ import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import gnu.trove.TIntHashSet;
-import gnu.trove.TIntIterator;
-import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.*;
-import java.util.function.IntFunction;
/**
* Set of VirtualFiles optimized for compact storage of very large number of files
@@ -146,31 +143,8 @@ public class CompactVirtualFileSet extends AbstractSet {
Iterator idsIterator = ids == null ? Collections.emptyIterator() :
ContainerUtil.mapIterator(ids.stream().iterator(), id -> virtualFileManager.findFileById(id));
Iterator idSetIterator = idSet == null ? Collections.emptyIterator() :
- mapIterator(idSet.iterator(), id -> virtualFileManager.findFileById(id));
+ ContainerUtil.mapIterator(idSet.iterator(), id -> virtualFileManager.findFileById(id));
Iterator weirdFileIterator = weirdFiles.iterator();
return ContainerUtil.filterIterator(ContainerUtil.concatIterators(idsIterator, idSetIterator, weirdFileIterator), Objects::nonNull);
}
-
- // todo move to ContainerUtil when ported util to java level 8
- @NotNull
- @Contract(pure=true)
- public static Iterator mapIterator(@NotNull final TIntIterator iterator, @NotNull final IntFunction extends U> mapper) {
- return new Iterator() {
- @Override
- public boolean hasNext() {
- return iterator.hasNext();
- }
-
- @Override
- public U next() {
- return mapper.apply(iterator.next());
- }
-
- @Override
- public void remove() {
- iterator.remove();
- }
- };
- }
-
}
diff --git a/platform/core-api/src/com/intellij/ui/SimpleTextAttributes.java b/platform/core-api/src/com/intellij/ui/SimpleTextAttributes.java
index 10d0971224ae..a530a539bbb6 100644
--- a/platform/core-api/src/com/intellij/ui/SimpleTextAttributes.java
+++ b/platform/core-api/src/com/intellij/ui/SimpleTextAttributes.java
@@ -21,7 +21,8 @@ public final class SimpleTextAttributes {
@MagicConstant(flags = {
STYLE_PLAIN, STYLE_BOLD, STYLE_ITALIC, STYLE_STRIKEOUT, STYLE_WAVED, STYLE_UNDERLINE,
- STYLE_BOLD_DOTTED_LINE, STYLE_SEARCH_MATCH, STYLE_SMALLER, STYLE_OPAQUE, STYLE_CLICKABLE})
+ STYLE_BOLD_DOTTED_LINE, STYLE_SEARCH_MATCH, STYLE_SMALLER, STYLE_OPAQUE,
+ STYLE_CLICKABLE, STYLE_HOVERED})
public @interface StyleAttributeConstant { }
public static final int STYLE_PLAIN = Font.PLAIN;
@@ -36,6 +37,7 @@ public final class SimpleTextAttributes {
public static final int STYLE_SMALLER = STYLE_SEARCH_MATCH << 1;
public static final int STYLE_OPAQUE = STYLE_SMALLER << 1;
public static final int STYLE_CLICKABLE = STYLE_OPAQUE << 1;
+ public static final int STYLE_HOVERED = STYLE_CLICKABLE << 1;
public static final SimpleTextAttributes REGULAR_ATTRIBUTES = new SimpleTextAttributes(STYLE_PLAIN, null);
public static final SimpleTextAttributes REGULAR_BOLD_ATTRIBUTES = new SimpleTextAttributes(STYLE_BOLD, null);
@@ -83,7 +85,7 @@ public final class SimpleTextAttributes {
this(null, fgColor, waveColor, style);
}
- public SimpleTextAttributes(@Nullable final Color bgColor, final Color fgColor, @Nullable final Color waveColor, @StyleAttributeConstant int style) {
+ public SimpleTextAttributes(@Nullable Color bgColor, Color fgColor, @Nullable Color waveColor, @StyleAttributeConstant int style) {
if ((~(STYLE_PLAIN |
STYLE_BOLD |
STYLE_ITALIC |
@@ -94,7 +96,8 @@ public final class SimpleTextAttributes {
STYLE_SEARCH_MATCH |
STYLE_SMALLER |
STYLE_OPAQUE |
- STYLE_CLICKABLE) & style) != 0) {
+ STYLE_CLICKABLE |
+ STYLE_HOVERED) & style) != 0) {
throw new IllegalArgumentException("Wrong style: " + style);
}
@@ -172,6 +175,10 @@ public final class SimpleTextAttributes {
return BitUtil.isSet(myStyle, STYLE_CLICKABLE);
}
+ public boolean isHovered() {
+ return BitUtil.isSet(myStyle, STYLE_HOVERED);
+ }
+
@NotNull
public static SimpleTextAttributes fromTextAttributes(TextAttributes attributes) {
if (attributes == null) return REGULAR_ATTRIBUTES;
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java b/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java
index b148eb75d822..2be73d1adb45 100644
--- a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java
+++ b/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java
@@ -152,6 +152,7 @@ public class PluginClassLoader extends UrlClassLoader {
private static final Set KOTLIN_STDLIB_CLASSES_USED_IN_SIGNATURES = ContainerUtil.set(
"kotlin.sequences.Sequence",
+ "kotlin.Lazy",
"kotlin.Unit",
"kotlin.Pair",
"kotlin.Triple",
diff --git a/platform/diff-api/src/com/intellij/diff/DiffDialogHints.java b/platform/diff-api/src/com/intellij/diff/DiffDialogHints.java
index c921ff64f97c..8e3946902d81 100644
--- a/platform/diff-api/src/com/intellij/diff/DiffDialogHints.java
+++ b/platform/diff-api/src/com/intellij/diff/DiffDialogHints.java
@@ -16,6 +16,7 @@
package com.intellij.diff;
import com.intellij.openapi.ui.WindowWrapper;
+import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,19 +33,21 @@ public class DiffDialogHints {
//
@Nullable private final WindowWrapper.Mode myMode;
- @Nullable private Component myParent;
+ @Nullable private final Component myParent;
+ @Nullable private final Consumer myWindowConsumer;
public DiffDialogHints(@Nullable WindowWrapper.Mode mode) {
this(mode, null);
}
public DiffDialogHints(@Nullable WindowWrapper.Mode mode, @Nullable Component parent) {
- myMode = mode;
- myParent = parent;
+ this(mode, parent, null);
}
- public void setParent(@Nullable Component value) {
- myParent = value;
+ public DiffDialogHints(@Nullable WindowWrapper.Mode mode, @Nullable Component parent, @Nullable Consumer windowConsumer) {
+ myMode = mode;
+ myParent = parent;
+ myWindowConsumer = windowConsumer;
}
//
@@ -60,4 +63,12 @@ public class DiffDialogHints {
public Component getParent() {
return myParent;
}
+
+ /**
+ * NB: Consumer might not be called at all (ex: for external diff/merge tools, that do not spawn WindowWrapper)
+ */
+ @Nullable
+ public Consumer getWindowConsumer() {
+ return myWindowConsumer;
+ }
}
diff --git a/platform/diff-api/src/com/intellij/diff/DiffManagerEx.java b/platform/diff-api/src/com/intellij/diff/DiffManagerEx.java
index cef525a236aa..5852f78c1bee 100644
--- a/platform/diff-api/src/com/intellij/diff/DiffManagerEx.java
+++ b/platform/diff-api/src/com/intellij/diff/DiffManagerEx.java
@@ -17,6 +17,7 @@ package com.intellij.diff;
import com.intellij.diff.chains.DiffRequestChain;
import com.intellij.diff.merge.MergeRequest;
+import com.intellij.diff.merge.MergeRequestProducer;
import com.intellij.diff.merge.MergeTool;
import com.intellij.diff.requests.DiffRequest;
import com.intellij.openapi.components.ServiceManager;
@@ -50,6 +51,9 @@ public abstract class DiffManagerEx extends DiffManager {
@CalledInAwt
public abstract void showMergeBuiltin(@Nullable Project project, @NotNull MergeRequest request);
+ @CalledInAwt
+ public abstract void showMergeBuiltin(@Nullable Project project, @NotNull MergeRequestProducer request, @NotNull DiffDialogHints hints);
+
@NotNull
public abstract List getDiffTools();
diff --git a/platform/diff-api/src/com/intellij/diff/DiffRequestFactory.java b/platform/diff-api/src/com/intellij/diff/DiffRequestFactory.java
index e6040a65403a..ac4fb0f677b8 100644
--- a/platform/diff-api/src/com/intellij/diff/DiffRequestFactory.java
+++ b/platform/diff-api/src/com/intellij/diff/DiffRequestFactory.java
@@ -91,6 +91,13 @@ public abstract class DiffRequestFactory {
@NotNull List contentTitles,
@Nullable Consumer super MergeResult> applyCallback) throws InvalidDiffRequestException;
+ @NotNull
+ public abstract MergeRequest createMergeRequest(@Nullable Project project,
+ @NotNull VirtualFile output,
+ @NotNull List byteContents,
+ @Nullable String title,
+ @NotNull List contentTitles) throws InvalidDiffRequestException;
+
@NotNull
public abstract TextMergeRequest createTextMergeRequest(@Nullable Project project,
@NotNull VirtualFile output,
diff --git a/platform/diff-api/src/com/intellij/diff/merge/MergeCallback.java b/platform/diff-api/src/com/intellij/diff/merge/MergeCallback.java
new file mode 100644
index 000000000000..5496e78237f6
--- /dev/null
+++ b/platform/diff-api/src/com/intellij/diff/merge/MergeCallback.java
@@ -0,0 +1,60 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.diff.merge;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.util.Consumer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.EventListener;
+
+import static com.intellij.openapi.diagnostic.Logger.getInstance;
+
+public class MergeCallback {
+ private static final Logger LOG = getInstance(MergeCallback.class);
+
+ private static final Key KEY = Key.create("com.intellij.diff.merge.MergeCallback");
+ private static final MergeCallback EMPTY = new MergeCallback();
+
+ public void applyResult(@NotNull MergeResult result) {
+ }
+
+ public boolean checkIsValid() {
+ return true;
+ }
+
+ public void addListener(@NotNull Listener listener, @NotNull Disposable disposable) {
+ }
+
+
+ @NotNull
+ public static T register(@NotNull T request, @Nullable MergeCallback callback) {
+ LOG.assertTrue(request.getUserData(KEY) == null);
+ if (callback != null) request.putUserData(KEY, callback);
+ return request;
+ }
+
+ @NotNull
+ public static T register(@NotNull T request, @Nullable Consumer super MergeResult> callback) {
+ return register(request, new MergeCallback() {
+ @Override
+ public void applyResult(@NotNull MergeResult result) {
+ if (callback != null) callback.consume(result);
+ }
+ });
+ }
+
+ @NotNull
+ public static MergeCallback getCallback(@NotNull MergeRequest request) {
+ MergeCallback callback = request.getUserData(KEY);
+ return callback != null ? callback : EMPTY;
+ }
+
+
+ public interface Listener extends EventListener {
+ default void fireConflictInvalid() {
+ }
+ }
+}
diff --git a/platform/diff-api/src/com/intellij/diff/merge/MergeRequestProducer.java b/platform/diff-api/src/com/intellij/diff/merge/MergeRequestProducer.java
new file mode 100644
index 000000000000..bc37feb8fdc9
--- /dev/null
+++ b/platform/diff-api/src/com/intellij/diff/merge/MergeRequestProducer.java
@@ -0,0 +1,19 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.diff.merge;
+
+import com.intellij.diff.chains.DiffRequestProducerException;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.util.UserDataHolder;
+import org.jetbrains.annotations.CalledInBackground;
+import org.jetbrains.annotations.NotNull;
+
+public interface MergeRequestProducer {
+ @NotNull
+ String getName();
+
+ @CalledInBackground
+ @NotNull
+ MergeRequest process(@NotNull UserDataHolder context, @NotNull ProgressIndicator indicator)
+ throws DiffRequestProducerException, ProcessCanceledException;
+}
diff --git a/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java
index 44d08d78e6bc..728d376f58be 100644
--- a/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java
+++ b/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java
@@ -133,6 +133,12 @@ public class DiffManagerImpl extends DiffManagerEx {
@Override
@CalledInAwt
public void showMergeBuiltin(@Nullable Project project, @NotNull MergeRequest request) {
- new MergeWindow(project, request).show();
+ new MergeWindow.ForRequest(project, request, DiffDialogHints.MODAL).show();
+ }
+
+ @Override
+ @CalledInAwt
+ public void showMergeBuiltin(@Nullable Project project, @NotNull MergeRequestProducer requestProducer, @NotNull DiffDialogHints hints) {
+ new MergeWindow.ForProducer(project, requestProducer, hints).show();
}
}
diff --git a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java
index d0f70ee940fe..6820af6d9159 100644
--- a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java
+++ b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java
@@ -18,6 +18,7 @@ package com.intellij.diff;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.contents.DocumentContent;
import com.intellij.diff.contents.FileContent;
+import com.intellij.diff.merge.MergeCallback;
import com.intellij.diff.merge.MergeRequest;
import com.intellij.diff.merge.MergeResult;
import com.intellij.diff.merge.TextMergeRequest;
@@ -232,7 +233,8 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
contents.add(myContentFactory.create(project, text, fileType));
}
- return new TextMergeRequestImpl(project, outputContent, originalContent, contents, title, titles, applyCallback);
+ TextMergeRequestImpl request = new TextMergeRequestImpl(project, outputContent, originalContent, contents, title, titles);
+ return MergeCallback.register(request, applyCallback);
}
@NotNull
@@ -243,14 +245,22 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
@Nullable String title,
@NotNull List contentTitles,
@Nullable Consumer super MergeResult> applyCallback) throws InvalidDiffRequestException {
- if (byteContents.size() != 3) throw new IllegalArgumentException();
- if (contentTitles.size() != 3) throw new IllegalArgumentException();
+ MergeRequest request = createMergeRequest(project, output, byteContents, title, contentTitles);
+ return MergeCallback.register(request, applyCallback);
+ }
+ @NotNull
+ @Override
+ public MergeRequest createMergeRequest(@Nullable Project project,
+ @NotNull VirtualFile output,
+ @NotNull List byteContents,
+ @Nullable String title,
+ @NotNull List contentTitles) throws InvalidDiffRequestException {
try {
- return createTextMergeRequest(project, output, byteContents, title, contentTitles, applyCallback);
+ return createTextMergeRequest(project, output, byteContents, title, contentTitles);
}
catch (InvalidDiffRequestException e) {
- return createBinaryMergeRequest(project, output, byteContents, title, contentTitles, applyCallback);
+ return createBinaryMergeRequest(project, output, byteContents, title, contentTitles);
}
}
@@ -262,6 +272,16 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
@Nullable String title,
@NotNull List contentTitles,
@Nullable Consumer super MergeResult> applyCallback) throws InvalidDiffRequestException {
+ TextMergeRequest request = createTextMergeRequest(project, output, byteContents, title, contentTitles);
+ return MergeCallback.register(request, applyCallback);
+ }
+
+ @NotNull
+ private TextMergeRequest createTextMergeRequest(@Nullable Project project,
+ @NotNull VirtualFile output,
+ @NotNull List byteContents,
+ @Nullable String title,
+ @NotNull List contentTitles) throws InvalidDiffRequestException {
if (byteContents.size() != 3) throw new IllegalArgumentException();
if (contentTitles.size() != 3) throw new IllegalArgumentException();
@@ -277,7 +297,7 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
contents.add(myContentFactory.createDocumentFromBytes(project, bytes, output));
}
- return new TextMergeRequestImpl(project, outputContent, originalContent, contents, title, contentTitles, applyCallback);
+ return new TextMergeRequestImpl(project, outputContent, originalContent, contents, title, contentTitles);
}
@NotNull
@@ -288,6 +308,16 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
@Nullable String title,
@NotNull List contentTitles,
@Nullable Consumer super MergeResult> applyCallback) throws InvalidDiffRequestException {
+ MergeRequest request = createBinaryMergeRequest(project, output, byteContents, title, contentTitles);
+ return MergeCallback.register(request, applyCallback);
+ }
+
+ @NotNull
+ private MergeRequest createBinaryMergeRequest(@Nullable Project project,
+ @NotNull VirtualFile output,
+ @NotNull List byteContents,
+ @Nullable String title,
+ @NotNull List contentTitles) throws InvalidDiffRequestException {
if (byteContents.size() != 3) throw new IllegalArgumentException();
if (contentTitles.size() != 3) throw new IllegalArgumentException();
@@ -301,7 +331,7 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
contents.add(myContentFactory.createFromBytes(project, bytes, output));
}
- return new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents, title, contentTitles, applyCallback);
+ return new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents, title, contentTitles);
}
catch (IOException e) {
throw new InvalidDiffRequestException("Can't read from file", e);
@@ -384,7 +414,9 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
byteContents.add(file.contentsToByteArray()); // TODO: we can read contents from file when needed
}
- return new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents, title, contentTitles, applyCallback);
+ BinaryMergeRequestImpl request = new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents,
+ title, contentTitles);
+ return MergeCallback.register(request, applyCallback);
}
catch (IOException e) {
throw new InvalidDiffRequestException("Can't read from file", e);
diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java
index e4d0053e27bd..c223edd68f1a 100644
--- a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java
+++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.WindowWrapper;
import com.intellij.openapi.ui.WindowWrapperBuilder;
import com.intellij.openapi.util.Disposer;
+import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -57,6 +58,9 @@ public abstract class DiffWindowBase {
.build();
myWrapper.setImages(DiffUtil.DIFF_FRAME_ICONS);
Disposer.register(myWrapper, myProcessor);
+
+ Consumer wrapperHandler = myHints.getWindowConsumer();
+ if (wrapperHandler != null) wrapperHandler.consume(myWrapper);
}
public void show() {
diff --git a/platform/diff-impl/src/com/intellij/diff/merge/ErrorMergeTool.java b/platform/diff-impl/src/com/intellij/diff/merge/ErrorMergeTool.java
index 70055802dc21..26c6e8dada33 100644
--- a/platform/diff-impl/src/com/intellij/diff/merge/ErrorMergeTool.java
+++ b/platform/diff-impl/src/com/intellij/diff/merge/ErrorMergeTool.java
@@ -48,12 +48,7 @@ public class ErrorMergeTool implements MergeTool {
myMergeRequest = request;
myPanel = new JPanel(new BorderLayout());
- myPanel.add(createComponent(), BorderLayout.CENTER);
- }
-
- @NotNull
- private JComponent createComponent() {
- return DiffUtil.createMessagePanel("Can't show diff");
+ myPanel.add(DiffUtil.createMessagePanel("Can't show merge"), BorderLayout.CENTER);
}
@NotNull
diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java b/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java
index 1fc51b5b6790..c66b6340f157 100644
--- a/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java
+++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeRequestProcessor.java
@@ -16,14 +16,25 @@ import com.intellij.notification.NotificationType;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.util.BackgroundTaskUtil;
+import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.BooleanGetter;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
+import com.intellij.ui.EditorNotificationPanel;
+import com.intellij.ui.LightColors;
+import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.JBEmptyBorder;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.CalledInAwt;
@@ -53,17 +64,17 @@ public abstract class MergeRequestProcessor implements Disposable {
@NotNull private final Wrapper myContentPanel;
@NotNull private final Wrapper myToolbarPanel;
@NotNull private final Wrapper myToolbarStatusPanel;
+ @NotNull private final Wrapper myNotificationPanel;
+ @NotNull private final Wrapper myButtonsPanel;
- @NotNull private final MergeRequest myRequest;
+ @Nullable private MergeRequest myRequest;
@NotNull private MergeTool.MergeViewer myViewer;
@Nullable private BooleanGetter myCloseHandler;
- @Nullable private BottomActions myBottomActions;
private boolean myConflictResolved = false;
- public MergeRequestProcessor(@Nullable Project project, @NotNull MergeRequest request) {
+ public MergeRequestProcessor(@Nullable Project project) {
myProject = project;
- myRequest = request;
myContext = new MyDiffContext();
myContext.putUserData(DiffUserDataKeys.PLACE, DiffPlaces.MERGE);
@@ -75,28 +86,23 @@ public abstract class MergeRequestProcessor implements Disposable {
myToolbarPanel = new Wrapper();
myToolbarPanel.setFocusable(true);
myToolbarStatusPanel = new Wrapper();
+ myNotificationPanel = new Wrapper();
+ myButtonsPanel = new Wrapper();
myPanel = JBUI.Panels.simplePanel(myMainPanel);
- JPanel topPanel = JBUI.Panels.simplePanel(myToolbarPanel).addToRight(myToolbarStatusPanel);
+ JPanel topPanel = JBUI.Panels.simplePanel(myToolbarPanel)
+ .addToRight(myToolbarStatusPanel)
+ .addToBottom(myNotificationPanel);
myMainPanel.add(topPanel, BorderLayout.NORTH);
myMainPanel.add(myContentPanel, BorderLayout.CENTER);
+ myMainPanel.add(myButtonsPanel, BorderLayout.SOUTH);
myMainPanel.setFocusTraversalPolicyProvider(true);
myMainPanel.setFocusTraversalPolicy(new MyFocusTraversalPolicy());
- MergeTool.MergeViewer viewer;
- try {
- viewer = getFittedTool().createComponent(myContext, myRequest);
- }
- catch (Throwable e) {
- LOG.error(e);
- viewer = ErrorMergeTool.INSTANCE.createComponent(myContext, myRequest);
- }
-
- myViewer = viewer;
- updateBottomActions();
+ myViewer = new MessageMergeViewer(myContext, "Loading...");
}
//
@@ -104,9 +110,50 @@ public abstract class MergeRequestProcessor implements Disposable {
//
@CalledInAwt
- public void init() {
- setTitle(myRequest.getTitle());
+ public void init(@NotNull MergeRequest request) {
+ setTitle(request.getTitle());
+
+ myRequest = request;
+ myViewer = createViewerFor(request);
initViewer();
+ installCallbackListener(myRequest);
+ }
+
+ @CalledInAwt
+ public void init(@NotNull MergeRequestProducer request) {
+ setTitle(request.getName());
+ initViewer();
+
+ ModalityState modality = ModalityState.stateForComponent(myPanel);
+ BackgroundTaskUtil.executeOnPooledThread(this, () -> {
+ try {
+ MergeRequest mergeRequest = request.process(myContext, ProgressManager.getInstance().getProgressIndicator());
+ ApplicationManager.getApplication().invokeLater(
+ () -> {
+ myRequest = mergeRequest;
+ swapViewer(createViewerFor(mergeRequest));
+ installCallbackListener(myRequest);
+ },
+ modality);
+ }
+ catch (Throwable e) {
+ LOG.warn(e);
+ ApplicationManager.getApplication().invokeLater(
+ () -> swapViewer(new MessageMergeViewer(myContext, "Can't show merge: " + e.getMessage())),
+ modality);
+ }
+ });
+ }
+
+ @NotNull
+ private MergeTool.MergeViewer createViewerFor(@NotNull MergeRequest request) {
+ try {
+ return getFittedTool(request).createComponent(myContext, request);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ return ErrorMergeTool.INSTANCE.createComponent(myContext, request);
+ }
}
@CalledInAwt
@@ -118,6 +165,8 @@ public abstract class MergeRequestProcessor implements Disposable {
buildToolbar(toolbarComponents.toolbarActions);
myToolbarStatusPanel.setContent(toolbarComponents.statusPanel);
myCloseHandler = toolbarComponents.closeHandler;
+
+ updateBottomActions();
}
@CalledInAwt
@@ -129,16 +178,49 @@ public abstract class MergeRequestProcessor implements Disposable {
myContentPanel.setContent(null);
myToolbarPanel.setContent(null);
myToolbarStatusPanel.setContent(null);
+ myButtonsPanel.setContent(null);
myCloseHandler = null;
- myBottomActions = null;
}
private void updateBottomActions() {
- myBottomActions = new BottomActions();
- myBottomActions.applyLeft = myViewer.getResolveAction(MergeResult.LEFT);
- myBottomActions.applyRight = myViewer.getResolveAction(MergeResult.RIGHT);
- myBottomActions.resolveAction = myViewer.getResolveAction(MergeResult.RESOLVED);
- myBottomActions.cancelAction = myViewer.getResolveAction(MergeResult.CANCEL);
+ Action applyLeft = myViewer.getResolveAction(MergeResult.LEFT);
+ Action applyRight = myViewer.getResolveAction(MergeResult.RIGHT);
+ Action resolveAction = myViewer.getResolveAction(MergeResult.RESOLVED);
+ Action cancelAction = myViewer.getResolveAction(MergeResult.CANCEL);
+
+ if (resolveAction != null) {
+ resolveAction.putValue(DialogWrapper.DEFAULT_ACTION, true);
+
+ new DumbAwareAction() {
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent e) {
+ resolveAction.actionPerformed(null);
+ }
+ }.registerCustomShortcutSet(CommonShortcuts.CTRL_ENTER, getRootPane(), this);
+ }
+
+ List leftActions = ContainerUtil.packNullables(applyLeft, applyRight);
+ List rightActions = SystemInfo.isMac ? ContainerUtil.packNullables(cancelAction, resolveAction)
+ : ContainerUtil.packNullables(resolveAction, cancelAction);
+
+ JRootPane rootPane = getRootPane();
+ JPanel buttonsPanel = new NonOpaquePanel(new BorderLayout());
+ buttonsPanel.setBorder(new JBEmptyBorder(UIUtil.PANEL_REGULAR_INSETS));
+
+ if (leftActions.size() > 0) {
+ buttonsPanel.add(createButtonsPanel(leftActions, rootPane), BorderLayout.WEST);
+ }
+ if (rightActions.size() > 0) {
+ buttonsPanel.add(createButtonsPanel(rightActions, rootPane), BorderLayout.EAST);
+ }
+
+ myButtonsPanel.setContent(buttonsPanel);
+ }
+
+ @NotNull
+ private static JPanel createButtonsPanel(@NotNull List actions, @Nullable JRootPane rootPane) {
+ List buttons = ContainerUtil.map(actions, action -> DialogWrapper.createJButtonForAction(action, rootPane));
+ return DialogWrapper.layoutButtonsPanel(buttons);
}
@NotNull
@@ -151,12 +233,14 @@ public abstract class MergeRequestProcessor implements Disposable {
DiffUtil.addActionBlock(group, viewerActions);
- List requestContextActions = myRequest.getUserData(DiffUserDataKeys.CONTEXT_ACTIONS);
+ List requestContextActions = myRequest != null ? myRequest.getUserData(DiffUserDataKeys.CONTEXT_ACTIONS) : null;
DiffUtil.addActionBlock(group, requestContextActions);
List contextActions = myContext.getUserData(DiffUserDataKeys.CONTEXT_ACTIONS);
DiffUtil.addActionBlock(group, contextActions);
+ DiffUtil.addActionBlock(group, ActionManager.getInstance().getAction(IdeActions.ACTION_CONTEXT_HELP));
+
return group;
}
@@ -173,10 +257,10 @@ public abstract class MergeRequestProcessor implements Disposable {
}
@NotNull
- private MergeTool getFittedTool() {
+ private MergeTool getFittedTool(@NotNull MergeRequest request) {
for (MergeTool tool : myAvailableTools) {
try {
- if (tool.canShow(myContext, myRequest)) return tool;
+ if (tool.canShow(myContext, request)) return tool;
}
catch (Throwable e) {
LOG.error(e);
@@ -191,6 +275,34 @@ public abstract class MergeRequestProcessor implements Disposable {
setWindowTitle(title);
}
+ private void installCallbackListener(@NotNull MergeRequest request) {
+ MergeCallback callback = MergeCallback.getCallback(request);
+ callback.addListener(new MergeCallback.Listener() {
+ @Override
+ public void fireConflictInvalid() {
+ showInvalidRequestNotification();
+ }
+ }, this);
+
+ if (!callback.checkIsValid()) {
+ showInvalidRequestNotification();
+ }
+ }
+
+ private void showInvalidRequestNotification() {
+ if (!myNotificationPanel.isNull()) return;
+
+ EditorNotificationPanel notification = new EditorNotificationPanel(LightColors.RED);
+ notification.setText("Conflict is not valid and no longer can be resolved.");
+ notification.createActionLabel("Abort Resolve", () -> {
+ applyRequestResult(MergeResult.CANCEL);
+ closeDialog();
+ });
+ myNotificationPanel.setContent(notification);
+ myMainPanel.validate();
+ myMainPanel.repaint();
+ }
+
@Override
public void dispose() {
if (myDisposed) return;
@@ -207,7 +319,7 @@ public abstract class MergeRequestProcessor implements Disposable {
@CalledInAwt
private void applyRequestResult(@NotNull MergeResult result) {
- if (myConflictResolved) return;
+ if (myConflictResolved || myRequest == null) return;
myConflictResolved = true;
try {
myRequest.applyResult(result);
@@ -220,6 +332,7 @@ public abstract class MergeRequestProcessor implements Disposable {
@CalledInAwt
private void reopenWithTool(@NotNull MergeTool tool) {
+ if (myRequest == null) return;
if (myConflictResolved) {
LOG.warn("Can't reopen with " + tool + " - conflict already resolved");
return;
@@ -239,11 +352,13 @@ public abstract class MergeRequestProcessor implements Disposable {
return;
}
+ swapViewer(newViewer);
+ }
+
+ private void swapViewer(@NotNull MergeTool.MergeViewer newViewer) {
DiffUtil.runPreservingFocus(myContext, () -> {
destroyViewer();
myViewer = newViewer;
- updateBottomActions();
- rebuildSouthPanel();
initViewer();
});
}
@@ -259,10 +374,11 @@ public abstract class MergeRequestProcessor implements Disposable {
protected void setWindowTitle(@NotNull String title) {
}
- protected abstract void rebuildSouthPanel();
-
public abstract void closeDialog();
+ @Nullable
+ protected abstract JRootPane getRootPane();
+
@Nullable
public T getContextUserData(@NotNull Key key) {
return myContext.getUserData(key);
@@ -302,16 +418,6 @@ public abstract class MergeRequestProcessor implements Disposable {
return myConflictResolved || myCloseHandler == null || myCloseHandler.get();
}
- @NotNull
- public BottomActions getBottomActions() {
- return myBottomActions != null ? myBottomActions : new BottomActions();
- }
-
- @Nullable
- public String getHelpId() {
- return PlatformDataKeys.HELP_ID.getData(myMainPanel);
- }
-
//
// Misc
//
@@ -404,7 +510,7 @@ public abstract class MergeRequestProcessor implements Disposable {
return myProject;
}
else if (PlatformDataKeys.HELP_ID.is(dataId)) {
- if (myRequest.getUserData(DiffUserDataKeys.HELP_ID) != null) {
+ if (myRequest != null && myRequest.getUserData(DiffUserDataKeys.HELP_ID) != null) {
return myRequest.getUserData(DiffUserDataKeys.HELP_ID);
}
else {
@@ -415,7 +521,7 @@ public abstract class MergeRequestProcessor implements Disposable {
return myViewer;
}
- DataProvider requestProvider = myRequest.getUserData(DiffUserDataKeys.DATA_PROVIDER);
+ DataProvider requestProvider = myRequest != null ? myRequest.getUserData(DiffUserDataKeys.DATA_PROVIDER) : null;
if (requestProvider != null) {
data = requestProvider.getData(dataId);
if (data != null) return data;
@@ -468,11 +574,4 @@ public abstract class MergeRequestProcessor implements Disposable {
MergeRequestProcessor.this.reopenWithTool(tool);
}
}
-
- public static class BottomActions {
- @Nullable public Action applyLeft;
- @Nullable public Action applyRight;
- @Nullable public Action resolveAction;
- @Nullable public Action cancelAction;
- }
}
diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java b/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java
index d943c09d8c6d..db0e29252087 100644
--- a/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java
+++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeUtil.java
@@ -15,6 +15,7 @@
*/
package com.intellij.diff.merge;
+import com.intellij.configurationStore.StoreReloadManager;
import com.intellij.diff.DiffContext;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.merge.MergeTool.MergeViewer;
@@ -34,6 +35,8 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.merge.MergeData;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.projectImport.ProjectOpenProcessor;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -43,6 +46,8 @@ import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.List;
+import static com.intellij.openapi.project.ProjectUtil.isProjectOrWorkspaceFile;
+
public class MergeUtil {
@NotNull
public static Action createSimpleResolveAction(@NotNull MergeResult result,
@@ -63,7 +68,7 @@ public class MergeUtil {
}
@NotNull
- public static String getResolveActionTitle(@NotNull MergeResult result, @NotNull MergeRequest request, @NotNull MergeContext context) {
+ public static String getResolveActionTitle(@NotNull MergeResult result, @Nullable MergeRequest request, @Nullable MergeContext context) {
Function getter = DiffUtil.getUserData(request, context, DiffUserDataKeysEx.MERGE_ACTION_CAPTIONS);
String message = getter != null ? getter.fun(result) : null;
if (message != null) return message;
@@ -156,6 +161,14 @@ public class MergeUtil {
return Messages.showYesNoDialog(component.getRootPane(), message, title, Messages.getQuestionIcon()) == Messages.YES;
}
+ public static boolean shouldRestoreOriginalContentOnCancel(@NotNull MergeRequest request) {
+ MergeCallback callback = MergeCallback.getCallback(request);
+ if (callback.checkIsValid()) return true;
+ return Messages.showYesNoDialog("Merge conflict is outdated. Restore file content prior to conflict resolve start?",
+ DiffBundle.message("cancel.visual.merge.dialog.title"), "Restore", "Do nothing",
+ Messages.getQuestionIcon()) == Messages.YES;
+ }
+
public static void putRevisionInfos(@NotNull MergeRequest request, @NotNull MergeData data) {
if (request instanceof ThreesideMergeRequest) {
List extends DiffContent> contents = ((ThreesideMergeRequest)request).getContents();
@@ -182,4 +195,18 @@ public class MergeUtil {
}
}
}
+
+ public static void reportProjectFileChangeIfNeeded(@Nullable Project project, @Nullable VirtualFile file) {
+ if (project != null && file != null && isProjectFile(file)) {
+ StoreReloadManager.getInstance().saveChangedProjectFile(file, project);
+ }
+ }
+
+ private static boolean isProjectFile(@NotNull VirtualFile file) {
+ if (file.isDirectory()) return false;
+ if (isProjectOrWorkspaceFile(file)) return true;
+
+ ProjectOpenProcessor importProvider = ProjectOpenProcessor.getImportProvider(file);
+ return importProvider != null && importProvider.lookForProjectsInDirectory();
+ }
}
diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MergeWindow.java b/platform/diff-impl/src/com/intellij/diff/merge/MergeWindow.java
index ff9ac360ce54..646e9a4f8675 100644
--- a/platform/diff-impl/src/com/intellij/diff/merge/MergeWindow.java
+++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeWindow.java
@@ -15,57 +15,58 @@
*/
package com.intellij.diff.merge;
+import com.intellij.diff.DiffDialogHints;
import com.intellij.diff.util.DiffUserDataKeys;
import com.intellij.diff.util.DiffUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.WindowWrapper;
+import com.intellij.openapi.ui.WindowWrapperBuilder;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.ui.components.panels.Wrapper;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.UIUtil;
+import com.intellij.util.Consumer;
+import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
-import java.util.List;
-public class MergeWindow {
+public abstract class MergeWindow {
private static final Logger LOG = Logger.getInstance(MergeWindow.class);
@Nullable private final Project myProject;
- @NotNull private final MergeRequest myMergeRequest;
+ @NotNull private final DiffDialogHints myHints;
- private MyDialog myWrapper;
+ private MergeRequestProcessor myProcessor;
+ private WindowWrapper myWrapper;
- public MergeWindow(@Nullable Project project, @NotNull MergeRequest mergeRequest) {
+ public MergeWindow(@Nullable Project project, @NotNull DiffDialogHints hints) {
myProject = project;
- myMergeRequest = mergeRequest;
+ myHints = hints;
}
protected void init() {
- MergeRequestProcessor processor = new MergeRequestProcessor(myProject, myMergeRequest) {
- @Override
- public void closeDialog() {
- myWrapper.doCancelAction();
- }
+ if (myWrapper != null) return;
- @Override
- protected void setWindowTitle(@NotNull String title) {
- myWrapper.setTitle(title);
- }
+ myProcessor = createProcessor();
- @Override
- protected void rebuildSouthPanel() {
- myWrapper.rebuildSouthPanel();
- }
- };
+ String dialogGroupKey = myProcessor.getContextUserData(DiffUserDataKeys.DIALOG_GROUP_KEY);
+ if (dialogGroupKey == null) dialogGroupKey = "MergeDialog";
- myWrapper = new MyDialog(processor);
- myWrapper.init();
+ myWrapper = new WindowWrapperBuilder(DiffUtil.getWindowMode(myHints), new MyPanel(myProcessor.getComponent()))
+ .setProject(myProject)
+ .setParent(myHints.getParent())
+ .setDimensionServiceKey(dialogGroupKey)
+ .setPreferredFocusedComponent(() -> myProcessor.getPreferredFocusedComponent())
+ .setOnShowCallback(() -> initProcessor(myProcessor))
+ .setOnCloseHandler(() -> myProcessor.checkCloseAction())
+ .build();
+ myWrapper.setImages(DiffUtil.DIFF_FRAME_ICONS);
+ Disposer.register(myWrapper, myProcessor);
+
+ Consumer wrapperHandler = myHints.getWindowConsumer();
+ if (wrapperHandler != null) wrapperHandler.consume(myWrapper);
}
public void show() {
@@ -77,100 +78,30 @@ public class MergeWindow {
myWrapper.show();
}
- // TODO: use WindowWrapper
- private static class MyDialog extends DialogWrapper {
- @NotNull private final MergeRequestProcessor myProcessor;
- @NotNull private final Wrapper mySouthPanel = new Wrapper();
-
- MyDialog(@NotNull MergeRequestProcessor processor) {
- super(processor.getProject(), true);
- myProcessor = processor;
- }
-
- @Override
- public void init() {
- super.init();
- Disposer.register(getDisposable(), myProcessor);
- UIUtil.runWhenWindowOpened(getWindow(), () -> myProcessor.init());
- }
-
- @Nullable
- @Override
- protected JComponent createCenterPanel() {
- return new MyPanel(myProcessor.getComponent());
- }
-
- @Nullable
- @Override
- protected JComponent createSouthPanel() {
- rebuildSouthPanel();
- return mySouthPanel;
- }
-
- @Nullable
- @Override
- public JComponent getPreferredFocusedComponent() {
- return myProcessor.getPreferredFocusedComponent();
- }
-
- @Nullable
- @Override
- protected String getDimensionServiceKey() {
- return StringUtil.notNullize(myProcessor.getContextUserData(DiffUserDataKeys.DIALOG_GROUP_KEY), "MergeDialog");
- }
-
- @NotNull
- @Override
- protected Action[] createActions() {
- MergeRequestProcessor.BottomActions bottomActions = myProcessor.getBottomActions();
- List actions = ContainerUtil.skipNulls(ContainerUtil.list(bottomActions.resolveAction, bottomActions.cancelAction));
- if (bottomActions.resolveAction != null) {
- bottomActions.resolveAction.putValue(DialogWrapper.DEFAULT_ACTION, true);
+ @NotNull
+ private MergeRequestProcessor createProcessor() {
+ return new MergeRequestProcessor(myProject) {
+ @Override
+ public void closeDialog() {
+ myWrapper.close();
}
- return actions.toArray(new Action[0]);
- }
- @NotNull
- @Override
- protected Action[] createLeftSideActions() {
- MergeRequestProcessor.BottomActions bottomActions = myProcessor.getBottomActions();
- List actions = ContainerUtil.skipNulls(ContainerUtil.list(bottomActions.applyLeft, bottomActions.applyRight));
- return actions.toArray(new Action[0]);
- }
+ @Override
+ protected void setWindowTitle(@NotNull String title) {
+ myWrapper.setTitle(title);
+ }
- @NotNull
- @Override
- protected Action getOKAction() {
- MergeRequestProcessor.BottomActions bottomActions = myProcessor.getBottomActions();
- if (bottomActions.resolveAction != null) return bottomActions.resolveAction;
- return super.getOKAction();
- }
-
- @NotNull
- @Override
- protected Action getCancelAction() {
- MergeRequestProcessor.BottomActions bottomActions = myProcessor.getBottomActions();
- if (bottomActions.cancelAction != null) return bottomActions.cancelAction;
- return super.getCancelAction();
- }
-
- @Nullable
- @Override
- protected String getHelpId() {
- return myProcessor.getHelpId();
- }
-
- @Override
- public void doCancelAction() {
- if (!myProcessor.checkCloseAction()) return;
- super.doCancelAction();
- }
-
- public void rebuildSouthPanel() {
- mySouthPanel.setContent(super.createSouthPanel());
- }
+ @Nullable
+ @Override
+ protected JRootPane getRootPane() {
+ RootPaneContainer container = ObjectUtils.tryCast(myWrapper.getWindow(), RootPaneContainer.class);
+ return container != null ? container.getRootPane() : null;
+ }
+ };
}
+ protected abstract void initProcessor(@NotNull MergeRequestProcessor processor);
+
private static class MyPanel extends JPanel {
MyPanel(@NotNull JComponent content) {
super(new BorderLayout());
@@ -184,4 +115,34 @@ public class MergeWindow {
return new Dimension(Math.max(windowSize.width, size.width), Math.max(windowSize.height, size.height));
}
}
+
+ public static class ForRequest extends MergeWindow {
+ @NotNull private final MergeRequest myMergeRequest;
+
+ public ForRequest(@Nullable Project project, @NotNull MergeRequest mergeRequest, @NotNull DiffDialogHints hints) {
+ super(project, hints);
+ myMergeRequest = mergeRequest;
+ }
+
+
+ @Override
+ protected void initProcessor(@NotNull MergeRequestProcessor processor) {
+ processor.init(myMergeRequest);
+ }
+ }
+
+ public static class ForProducer extends MergeWindow {
+ @NotNull private final MergeRequestProducer myMergeRequestProducer;
+
+ public ForProducer(@Nullable Project project, @NotNull MergeRequestProducer mergeRequestProducer, @NotNull DiffDialogHints hints) {
+ super(project, hints);
+ myMergeRequestProducer = mergeRequestProducer;
+ }
+
+
+ @Override
+ protected void initProcessor(@NotNull MergeRequestProcessor processor) {
+ processor.init(myMergeRequestProducer);
+ }
+ }
}
diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MessageMergeViewer.java b/platform/diff-impl/src/com/intellij/diff/merge/MessageMergeViewer.java
new file mode 100644
index 000000000000..7a563b3f088c
--- /dev/null
+++ b/platform/diff-impl/src/com/intellij/diff/merge/MessageMergeViewer.java
@@ -0,0 +1,59 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.diff.merge;
+
+import com.intellij.diff.util.DiffUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+
+class MessageMergeViewer implements MergeTool.MergeViewer {
+ @NotNull private final MergeContext myMergeContext;
+
+ @NotNull private final JPanel myPanel;
+
+ MessageMergeViewer(@NotNull MergeContext context, @NotNull String message) {
+ myMergeContext = context;
+
+ myPanel = new JPanel(new BorderLayout());
+ myPanel.add(DiffUtil.createMessagePanel(message), BorderLayout.CENTER);
+ }
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public MergeTool.ToolbarComponents init() {
+ return new MergeTool.ToolbarComponents();
+ }
+
+ @Nullable
+ @Override
+ public Action getResolveAction(@NotNull final MergeResult result) {
+ if (result != MergeResult.CANCEL) return null;
+
+ String caption = MergeUtil.getResolveActionTitle(result, null, myMergeContext);
+ return new AbstractAction(caption) {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myMergeContext.finishMerge(result);
+ }
+ };
+ }
+
+ @Override
+ public void dispose() {
+ }
+}
diff --git a/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java b/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java
index 2d019cf521c1..4a3566cece21 100644
--- a/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java
+++ b/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java
@@ -30,6 +30,7 @@ import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.diff.DiffBundle;
@@ -43,7 +44,6 @@ import com.intellij.openapi.editor.markup.MarkupEditorFilter;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.util.BackgroundTaskUtil;
import com.intellij.openapi.progress.util.ProgressWindow;
import com.intellij.openapi.project.DumbAware;
@@ -80,6 +80,11 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
@NotNull private final MyThreesideViewer myViewer;
+ private final Action myCancelResolveAction;
+ private final Action myLeftResolveAction;
+ private final Action myRightResolveAction;
+ private final Action myAcceptResolveAction;
+
public TextMergeViewer(@NotNull MergeContext context, @NotNull TextMergeRequest request) {
myMergeContext = context;
myMergeRequest = request;
@@ -91,6 +96,11 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
diffRequest.putUserData(DiffUserDataKeys.FORCE_READ_ONLY_CONTENTS, new boolean[]{true, false, true});
myViewer = new MyThreesideViewer(diffContext, diffRequest);
+
+ myCancelResolveAction = myViewer.getResolveAction(MergeResult.CANCEL);
+ myLeftResolveAction = myViewer.getResolveAction(MergeResult.LEFT);
+ myRightResolveAction = myViewer.getResolveAction(MergeResult.RIGHT);
+ myAcceptResolveAction = myViewer.getResolveAction(MergeResult.RESOLVED);
}
@NotNull
@@ -145,7 +155,18 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
@Nullable
@Override
public Action getResolveAction(@NotNull MergeResult result) {
- return myViewer.getResolveAction(result);
+ switch (result) {
+ case CANCEL:
+ return myCancelResolveAction;
+ case LEFT:
+ return myLeftResolveAction;
+ case RIGHT:
+ return myRightResolveAction;
+ case RESOLVED:
+ return myAcceptResolveAction;
+ default:
+ return null;
+ }
}
@Override
@@ -383,34 +404,25 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
// This is made to reduce unwanted modifications before rediff is finished.
// It could happen between this init() EDT chunk and invokeLater().
getEditor().setViewer(true);
+ myLoadingPanel.startLoading();
+ myAcceptResolveAction.setEnabled(false);
- // we need invokeLater() here because viewer is partially-initialized (ex: there are no toolbar or status panel)
- // user can see this state while we're showing progress indicator, so we want let init() to finish.
- ApplicationManager.getApplication().invokeLater(() -> ProgressManager.getInstance().run(new Task.Modal(getProject(), "Computing Differences...", true) {
- private Runnable myCallback;
+ BackgroundTaskUtil.executeOnPooledThread(this, () -> {
+ ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- myCallback = doPerformRediff(indicator);
+ Runnable callback;
+ try {
+ callback = doPerformRediff(indicator);
}
-
- @Override
- public void onCancel() {
- myMergeContext.finishMerge(MergeResult.CANCEL);
+ catch (ProcessCanceledException e) {
+ callback = () -> myMergeContext.finishMerge(MergeResult.CANCEL);
}
-
- @Override
- public void onThrowable(@NotNull Throwable error) {
- LOG.error(error);
- myMergeContext.finishMerge(MergeResult.CANCEL);
+ catch (Throwable e) {
+ LOG.error(e);
+ callback = () -> myMergeContext.finishMerge(MergeResult.CANCEL);
}
-
- @Override
- public void onSuccess() {
- if (isDisposed()) return;
- myCallback.run();
- }
- }));
+ ApplicationManager.getApplication().invokeLater(callback, ModalityState.stateForComponent(myPanel));
+ });
}
@NotNull
@@ -453,6 +465,8 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
private void apply(@NotNull List fragments,
@NotNull List conflictTypes,
@NotNull IgnorePolicy ignorePolicy) {
+ if (isDisposed()) return;
+
clearDiffPresentation();
resetChangeCounters();
@@ -481,6 +495,8 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
myStatusPanel.update();
getEditor().setViewer(false);
+ myLoadingPanel.stopLoading();
+ myAcceptResolveAction.setEnabled(true);
myInnerDiffWorker.onEverythingChanged();
myInitialRediffFinished = true;
@@ -676,7 +692,7 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
String message = DiffBundle.message("merge.all.changes.processed.message.text");
DiffUtil.showSuccessPopup(message, point, this, () -> {
- if (isDisposed()) return;
+ if (isDisposed() || myLoadingPanel.isLoading()) return;
destroyChangedBlocks();
myMergeContext.finishMerge(MergeResult.RESOLVED);
});
diff --git a/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java b/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java
index 6e09badee659..dd54bd422acb 100644
--- a/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java
+++ b/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java
@@ -19,7 +19,9 @@ import com.intellij.CommonBundle;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.contents.FileContent;
import com.intellij.diff.merge.BinaryMergeRequest;
+import com.intellij.diff.merge.MergeCallback;
import com.intellij.diff.merge.MergeResult;
+import com.intellij.diff.merge.MergeUtil;
import com.intellij.diff.util.DiffUtil;
import com.intellij.diff.util.ThreeSide;
import com.intellij.openapi.command.WriteCommandAction;
@@ -27,7 +29,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -47,16 +48,13 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest {
@Nullable private final String myTitle;
@NotNull private final List myTitles;
- @Nullable private final Consumer super MergeResult> myApplyCallback;
-
public BinaryMergeRequestImpl(@Nullable Project project,
@NotNull FileContent file,
@NotNull byte[] originalContent,
@NotNull List contents,
@NotNull List byteContents,
@Nullable String title,
- @NotNull List contentTitles,
- @Nullable Consumer super MergeResult> applyCallback) {
+ @NotNull List contentTitles) {
assert byteContents.size() == 3;
assert contents.size() == 3;
assert contentTitles.size() == 3;
@@ -70,8 +68,6 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest {
myTitle = title;
myTitles = contentTitles;
- myApplyCallback = applyCallback;
-
onAssigned(true);
}
@@ -111,7 +107,7 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest {
final byte[] applyContent;
switch (result) {
case CANCEL:
- applyContent = myOriginalContent;
+ applyContent = MergeUtil.shouldRestoreOriginalContentOnCancel(this) ? myOriginalContent : null;
break;
case LEFT:
applyContent = ThreeSide.LEFT.select(myByteContents);
@@ -140,7 +136,7 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest {
});
}
- if (myApplyCallback != null) myApplyCallback.consume(result);
+ MergeCallback.getCallback(this).applyResult(result);
}
finally {
onAssigned(false);
diff --git a/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java b/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java
index 104b1945ee16..e392c199ee5d 100644
--- a/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java
+++ b/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java
@@ -16,13 +16,14 @@
package com.intellij.diff.requests;
import com.intellij.diff.contents.DocumentContent;
+import com.intellij.diff.merge.MergeCallback;
import com.intellij.diff.merge.MergeResult;
+import com.intellij.diff.merge.MergeUtil;
import com.intellij.diff.merge.TextMergeRequest;
import com.intellij.diff.util.DiffUtil;
import com.intellij.diff.util.ThreeSide;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,15 +39,12 @@ public class TextMergeRequestImpl extends TextMergeRequest {
@Nullable private final String myTitle;
@NotNull private final List myTitles;
- @Nullable private final Consumer super MergeResult> myApplyCallback;
-
public TextMergeRequestImpl(@Nullable Project project,
@NotNull DocumentContent output,
@NotNull CharSequence originalContent,
@NotNull List contents,
@Nullable String title,
- @NotNull List contentTitles,
- @Nullable Consumer super MergeResult> applyCallback) {
+ @NotNull List contentTitles) {
assert contents.size() == 3;
assert contentTitles.size() == 3;
myProject = project;
@@ -58,8 +56,6 @@ public class TextMergeRequestImpl extends TextMergeRequest {
myTitles = contentTitles;
myTitle = title;
- myApplyCallback = applyCallback;
-
onAssigned(true);
}
@@ -93,7 +89,7 @@ public class TextMergeRequestImpl extends TextMergeRequest {
final CharSequence applyContent;
switch (result) {
case CANCEL:
- applyContent = myOriginalContent;
+ applyContent = MergeUtil.shouldRestoreOriginalContentOnCancel(this) ? myOriginalContent : null;
break;
case LEFT:
CharSequence leftContent = ThreeSide.LEFT.select(getContents()).getDocument().getImmutableCharSequence();
@@ -114,7 +110,7 @@ public class TextMergeRequestImpl extends TextMergeRequest {
DiffUtil.executeWriteCommand(myOutput.getDocument(), myProject, null, () -> myOutput.getDocument().setText(applyContent));
}
- if (myApplyCallback != null) myApplyCallback.consume(result);
+ MergeCallback.getCallback(this).applyResult(result);
}
finally {
onAssigned(false);
diff --git a/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java
index 58438b1278bf..b5325c669cea 100644
--- a/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java
+++ b/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java
@@ -28,14 +28,11 @@ import com.intellij.openapi.ListSelection;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ThrowableConvertor;
+import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -88,7 +85,7 @@ public class ExternalDiffTool {
private static List loadRequestsUnderProgress(@Nullable Project project,
@NotNull DiffRequestChain chain) throws Throwable {
if (chain instanceof AsyncDiffRequestChain) {
- return loadInBackground(project, "Loading Requests", indicator -> {
+ return VcsUtil.computeWithModalProgress(project, "Loading Requests", true, indicator -> {
ListSelection extends DiffRequestProducer> listSelection = ((AsyncDiffRequestChain)chain).loadRequestsInBackground();
return collectRequests(project, listSelection.getList(), listSelection.getSelectedIndex(), indicator);
});
@@ -97,7 +94,9 @@ public class ExternalDiffTool {
List extends DiffRequestProducer> allProducers = chain.getRequests();
int index = chain.getIndex();
- return loadInBackground(project, "Loading Requests", indicator -> collectRequests(project, allProducers, index, indicator));
+ return VcsUtil.computeWithModalProgress(project, "Loading Requests", true, indicator -> {
+ return collectRequests(project, allProducers, index, indicator);
+ });
}
}
@@ -162,28 +161,4 @@ public class ExternalDiffTool {
}
return true;
}
-
-
- @Nullable
- private static T loadInBackground(@Nullable Project project,
- @NotNull String title,
- @NotNull ThrowableConvertor computable) throws Throwable {
- final Ref requestsRef = new Ref<>();
- final Ref exceptionRef = new Ref<>();
-
- ProgressManager.getInstance().run(new Task.Modal(project, title, true) {
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- try {
- requestsRef.set(computable.convert(indicator));
- }
- catch (Throwable e) {
- exceptionRef.set(e);
- }
- }
- });
-
- if (!exceptionRef.isNull()) throw exceptionRef.get();
- return requestsRef.get();
- }
}
diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/side/ThreesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/side/ThreesideDiffViewer.java
index 4693a8310f62..0d3190b73d00 100644
--- a/platform/diff-impl/src/com/intellij/diff/tools/util/side/ThreesideDiffViewer.java
+++ b/platform/diff-impl/src/com/intellij/diff/tools/util/side/ThreesideDiffViewer.java
@@ -37,18 +37,21 @@ import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.util.Disposer;
import com.intellij.pom.Navigatable;
+import com.intellij.ui.components.JBLoadingPanel;
import org.jetbrains.annotations.CalledInAwt;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public abstract class ThreesideDiffViewer extends ListenerDiffViewerBase {
@NotNull protected final SimpleDiffPanel myPanel;
@NotNull protected final ThreesideContentPanel myContentPanel;
+ @NotNull protected final JBLoadingPanel myLoadingPanel;
@NotNull private final List myHolders;
@@ -63,7 +66,10 @@ public abstract class ThreesideDiffViewer extends Listen
myFocusTrackerSupport = new FocusTrackerSupport.Threeside(myHolders);
myContentPanel = new ThreesideContentPanel(myHolders, titlePanel);
- myPanel = new SimpleDiffPanel(myContentPanel, this, context);
+ myLoadingPanel = new JBLoadingPanel(new BorderLayout(), this, 300);
+ myLoadingPanel.add(myContentPanel, BorderLayout.CENTER);
+
+ myPanel = new SimpleDiffPanel(myLoadingPanel, this, context);
}
@Override
diff --git a/platform/dvcs-impl/src/META-INF/dvcs.xml b/platform/dvcs-impl/src/META-INF/dvcs.xml
index c408414ef181..8d43989226f1 100644
--- a/platform/dvcs-impl/src/META-INF/dvcs.xml
+++ b/platform/dvcs-impl/src/META-INF/dvcs.xml
@@ -7,6 +7,7 @@
+
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/repo/ClonePathProvider.java b/platform/dvcs-impl/src/com/intellij/dvcs/repo/ClonePathProvider.java
new file mode 100644
index 000000000000..d282a615b990
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/repo/ClonePathProvider.java
@@ -0,0 +1,63 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.dvcs.repo;
+
+import com.intellij.dvcs.DvcsRememberedInputs;
+import com.intellij.ide.impl.ProjectUtil;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.util.PathUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.net.URLDecoder;
+
+/**
+ * Provides default paths for clone repository functionality.
+ * Default implementation suggests to clone a project to the `[project dir]/[last url component]`.
+ */
+public abstract class ClonePathProvider {
+ private static final ExtensionPointName EP_NAME =
+ ExtensionPointName.create("com.intellij.clonePathProvider");
+
+ @NotNull
+ public static String defaultParentDirectoryPath(@NotNull Project project, @NotNull DvcsRememberedInputs rememberedInputs) {
+ for (ClonePathProvider provider : EP_NAME.getExtensionList()) {
+ String directoryPath = provider.getParentDirectoryPath(project, rememberedInputs);
+ if (StringUtil.isNotEmpty(directoryPath)) {
+ return directoryPath;
+ }
+ }
+
+ String parentDirectory = rememberedInputs.getCloneParentDir();
+ return StringUtil.isEmptyOrSpaces(parentDirectory) ? ProjectUtil.getBaseDir() : parentDirectory;
+ }
+
+ @NotNull
+ public static String relativeDirectoryPathForVcsUrl(@NotNull Project project, @NotNull String vcsUrl) {
+ for (ClonePathProvider provider : EP_NAME.getExtensionList()) {
+ String directoryPath = provider.getRelativeDirectoryPathForVcsUrl(project, vcsUrl);
+ if (StringUtil.isNotEmpty(directoryPath)) {
+ return directoryPath;
+ }
+ }
+ return safeUrlDecode(PathUtil.getFileName(vcsUrl));
+ }
+
+ @NotNull
+ private static String safeUrlDecode(@NotNull String encoded) {
+ try {
+ return URLDecoder.decode(encoded, CharsetToolkit.UTF8);
+ }
+ catch (Exception e) {
+ return encoded;
+ }
+ }
+
+ @Nullable
+ public abstract String getParentDirectoryPath(@NotNull Project project, @NotNull DvcsRememberedInputs rememberedInputs);
+
+ @Nullable
+ public abstract String getRelativeDirectoryPathForVcsUrl(@NotNull Project project, @NotNull String vcsUrl);
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java
index b2b4cac6cb2f..d36e53bd8071 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java
@@ -7,7 +7,7 @@ import com.intellij.dvcs.DvcsUtil;
import com.intellij.dvcs.hosting.RepositoryHostingService;
import com.intellij.dvcs.hosting.RepositoryListLoader;
import com.intellij.dvcs.hosting.RepositoryListLoadingException;
-import com.intellij.ide.impl.ProjectUtil;
+import com.intellij.dvcs.repo.ClonePathProvider;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.IdeActions;
@@ -30,7 +30,6 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBOptionButton;
@@ -51,11 +50,9 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
-import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
-import java.net.URLDecoder;
import java.nio.file.*;
import java.util.List;
import java.util.*;
@@ -181,8 +178,6 @@ public abstract class CloneDvcsDialog extends DialogWrapper {
}
private void initComponents(@Nullable String defaultUrl) {
- String parentDirectory = getRememberedInputs().getCloneParentDir();
-
myRepositoryUrlComboboxModel = new CollectionComboBoxModel<>();
myRepositoryUrlField = TextFieldWithAutoCompletion.create(myProject,
myRepositoryUrlComboboxModel.getItems(),
@@ -204,7 +199,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper {
myRepositoryUrlField.addDocumentListener(new DocumentListener() {
@Override
public void documentChanged(@NotNull com.intellij.openapi.editor.event.DocumentEvent event) {
- myDirectoryField.trySetChildPath(defaultDirectoryName(myRepositoryUrlField.getText().trim()));
+ myDirectoryField.trySetChildPath(defaultDirectoryPath(myRepositoryUrlField.getText().trim()));
}
});
myRepositoryUrlField.addDocumentListener(new DocumentListener() {
@@ -220,9 +215,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper {
FileChooserDescriptor fcd = FileChooserDescriptorFactory.createSingleFolderDescriptor();
fcd.setShowFileSystemRoots(true);
fcd.setHideIgnored(false);
- myDirectoryField = new MyTextFieldWithBrowseButton(StringUtil.isEmptyOrSpaces(parentDirectory)
- ? ProjectUtil.getBaseDir()
- : parentDirectory);
+ myDirectoryField = new MyTextFieldWithBrowseButton(ClonePathProvider.defaultParentDirectoryPath(myProject, getRememberedInputs()));
myDirectoryField.addBrowseFolderListener(DvcsBundle.getString("clone.destination.directory.browser.title"),
DvcsBundle.getString("clone.destination.directory.browser.description"),
myProject,
@@ -517,16 +510,6 @@ public abstract class CloneDvcsDialog extends DialogWrapper {
rememberedInputs.setCloneParentDir(getParentDirectory());
}
- @NotNull
- private static String safeUrlDecode(@NotNull String encoded) {
- try {
- return URLDecoder.decode(encoded, CharsetToolkit.UTF8);
- }
- catch (Exception e) {
- return encoded;
- }
- }
-
/**
* Get default name for checked out directory
*
@@ -534,30 +517,8 @@ public abstract class CloneDvcsDialog extends DialogWrapper {
* @return a default repository name
*/
@NotNull
- private String defaultDirectoryName(@NotNull final String url) {
- return stripSuffix(safeUrlDecode(getLastPathFragment(url)));
- }
-
- @NotNull
- private String stripSuffix(@NotNull String directoryName) {
- return directoryName.endsWith(myVcsDirectoryName)
- ? directoryName.substring(0, directoryName.length() - myVcsDirectoryName.length())
- : directoryName;
- }
-
- @NotNull
- private static String getLastPathFragment(@NotNull final String url) {
- // Suppose it's a URL
- int i = url.lastIndexOf('/');
-
- // No? Maybe win-style path?
- if (i == -1 && File.separatorChar != '/') i = url.lastIndexOf(File.separatorChar);
-
- if (i < 0) return "";
-
- if (i == url.length() - 1) return getLastPathFragment(url.substring(0, i));
-
- return url.substring(i + 1);
+ private String defaultDirectoryPath(@NotNull final String url) {
+ return StringUtil.trimEnd(ClonePathProvider.relativeDirectoryPathForVcsUrl(myProject, url), myVcsDirectoryName);
}
@Nullable
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemEventDispatcher.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemEventDispatcher.kt
index 2f56c1ada679..c32dcfef2255 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemEventDispatcher.kt
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemEventDispatcher.kt
@@ -16,7 +16,7 @@ import java.io.Closeable
*/
@ApiStatus.Experimental
class ExternalSystemEventDispatcher(task: ExternalSystemTask,
- private val progressListener: BuildProgressListener?) : Closeable, Appendable, BuildProgressListener {
+ progressListener: BuildProgressListener?) : Closeable, Appendable, BuildProgressListener {
private var outputMessageDispatcher: ExternalSystemOutputMessageDispatcher? = null
init {
@@ -37,8 +37,8 @@ class ExternalSystemEventDispatcher(task: ExternalSystemTask,
foundFactory = it
}
}
- outputMessageDispatcher = foundFactory?.create(task.getId(), progressListener, buildOutputParsers)
- ?: DefaultOutputMessageDispatcher(task.getId(), progressListener, buildOutputParsers)
+ outputMessageDispatcher = foundFactory?.create(task.id, progressListener, buildOutputParsers)
+ ?: DefaultOutputMessageDispatcher(task.id, progressListener, buildOutputParsers)
}
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt
index be59d7a0ca99..087e0da49c12 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt
@@ -26,7 +26,6 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage
private var isDisposed = false
private val mutex = Any()
- private val postponedSourceFolderCreator = PostponedSourceFolderCreator()
private val sourceFolders = PathPrefixTreeMapImpl()
private val sourceFoldersByModule = THashMap()
@@ -63,8 +62,6 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage
override fun dispose() {
assert(!isDisposed) { "Source folder manager already disposed" }
isDisposed = true
- val virtualFileManager = VirtualFileManager.getInstance()
- virtualFileManager.removeVirtualFileListener(postponedSourceFolderCreator)
}
fun isDisposed() = isDisposed
@@ -131,6 +128,6 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage
init {
val virtualFileManager = VirtualFileManager.getInstance()
- virtualFileManager.addVirtualFileListener(postponedSourceFolderCreator, project)
+ virtualFileManager.addVirtualFileListener(PostponedSourceFolderCreator(), this)
}
}
\ No newline at end of file
diff --git a/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java b/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java
index f2a9dcfeb97a..9e2fa4e09f72 100644
--- a/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java
+++ b/platform/indexing-api/src/com/intellij/util/indexing/IdFilter.java
@@ -16,6 +16,7 @@
package com.intellij.util.indexing;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentIterator;
@@ -35,12 +36,13 @@ public abstract class IdFilter {
private static final Key> INSIDE_PROJECT = Key.create("INSIDE_PROJECT");
private static final Key> OUTSIDE_PROJECT = Key.create("OUTSIDE_PROJECT");
- public static IdFilter getProjectIdFilter(final Project project, final boolean includeNonProjectItems) {
+ @NotNull
+ public static IdFilter getProjectIdFilter(@NotNull Project project, final boolean includeNonProjectItems) {
Key> key = includeNonProjectItems ? OUTSIDE_PROJECT : INSIDE_PROJECT;
+ CachedValueProvider provider = () -> CachedValueProvider.Result.create(buildProjectIdFilter(project, includeNonProjectItems),
+ ProjectRootManager.getInstance(project), VirtualFileManager.VFS_STRUCTURE_MODIFICATIONS);
return CachedValuesManager.getManager(project).getCachedValue(project, key,
- () -> CachedValueProvider.Result
- .create(buildProjectIdFilter(project, includeNonProjectItems),
- ProjectRootManager.getInstance(project), VirtualFileManager.VFS_STRUCTURE_MODIFICATIONS), false);
+ provider, false);
}
@NotNull
@@ -56,8 +58,9 @@ public abstract class IdFilter {
if (!includeNonProjectItems) {
ProjectRootManager.getInstance(project).getFileIndex().iterateContent(iterator);
- } else {
- FileBasedIndex.getInstance().iterateIndexableFiles(iterator, project, null);
+ }
+ else {
+ FileBasedIndex.getInstance().iterateIndexableFiles(iterator, project, ProgressIndicatorProvider.getGlobalProgressIndicator());
}
if (LOG.isDebugEnabled()) {
diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java
index 0d223df3d8bd..bbec44cadbbf 100644
--- a/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java
+++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/LowLevelSearchUtil.java
@@ -193,23 +193,21 @@ public class LowLevelSearchUtil {
FileViewProvider viewProvider,
CharSequence buffer,
TextRange range) {
- StringBuilder msg = new StringBuilder()
- .append("Range for element: '").append(scope).append("' = ").append(range)
- .append(" is out of file '").append(file).append("' range: ").append(file.getTextRange())
- .append("; file contents length: ").append(buffer.length())
- .append("\n file provider: ").append(viewProvider);
+ String msg = "Range for element: '" + scope + "' = " + range + " is out of file '" + file + "' range: " + file.getTextRange();
+ msg += "; file contents length: " + buffer.length();
+ msg += "\n file provider: " + viewProvider;
Document document = viewProvider.getDocument();
if (document != null) {
- msg.append("\n committed=").append(PsiDocumentManager.getInstance(file.getProject()).isCommitted(document));
+ msg += "\n committed=" + PsiDocumentManager.getInstance(file.getProject()).isCommitted(document);
}
for (Language language : viewProvider.getLanguages()) {
final PsiFile root = viewProvider.getPsi(language);
- msg.append("\n root ").append(language).append(" length=").append(root.getTextLength());
- if (root instanceof PsiFileImpl) {
- msg.append("; contentsLoaded=").append(((PsiFileImpl)root).isContentsLoaded());
- }
+ //noinspection StringConcatenationInLoop
+ msg += "\n root " + language + " length=" + root.getTextLength() + (root instanceof PsiFileImpl
+ ? "; contentsLoaded=" + ((PsiFileImpl)root).isContentsLoaded() : "");
}
- LOG.error(msg.toString());
+
+ LOG.error(msg);
}
// map (text to be scanned -> list of cached pairs of (searcher used to scan text, occurrences found))
diff --git a/platform/indexing-impl/src/com/intellij/psi/search/FileNameIndexService.java b/platform/indexing-impl/src/com/intellij/psi/search/FileNameIndexService.java
index a1a2a7a3fe13..66917f80b498 100644
--- a/platform/indexing-impl/src/com/intellij/psi/search/FileNameIndexService.java
+++ b/platform/indexing-impl/src/com/intellij/psi/search/FileNameIndexService.java
@@ -29,7 +29,7 @@ interface FileNameIndexService {
@NotNull
Collection getVirtualFilesByName(Project project, @NotNull String name, @NotNull GlobalSearchScope scope, @Nullable IdFilter idFilter);
- void processAllFileNames(@NotNull Processor processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter);
+ void processAllFileNames(@NotNull Processor super String> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter);
@NotNull
Collection getFilesWithFileType(@NotNull FileType type, @NotNull GlobalSearchScope scope);
diff --git a/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java b/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java
index 0687c3eff0cc..7130c419e978 100644
--- a/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java
+++ b/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java
@@ -56,7 +56,7 @@ public class FilenameIndex {
return ArrayUtil.toStringArray(names);
}
- public static void processAllFileNames(@NotNull Processor processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter) {
+ public static void processAllFileNames(@NotNull Processor super String> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter) {
getService().processAllFileNames(processor, scope, filter);
}
diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/BraceStyleAccessor.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/BraceStyleAccessor.java
index c704bf96a70f..f795d40d0033 100644
--- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/BraceStyleAccessor.java
+++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/BraceStyleAccessor.java
@@ -2,54 +2,29 @@
package com.intellij.application.options.codeStyle.properties;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
-import com.intellij.util.containers.BidirectionalMap;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.List;
-class BraceStyleAccessor extends ExternalStringAccessor implements CodeStyleChoiceList {
- private final static BidirectionalMap BRACE_STYLE_MAP = new BidirectionalMap<>();
-
- public static final String VALUE_END_OF_LINE = "end_of_line";
- public static final String VALUE_NEXT_LINE = "next_line";
- public static final String VALUE_NEXT_LINE_IF_WRAPPED = "next_line_if_wrapped";
- public static final String VALUE_WHITESMITHS = "whitesmiths";
- public static final String VALUE_GNU = "gnu";
-
- private final static List ALL_VALUES =
- Arrays.asList(VALUE_END_OF_LINE, VALUE_NEXT_LINE, VALUE_NEXT_LINE_IF_WRAPPED, VALUE_WHITESMITHS, VALUE_GNU);
-
- static {
- BRACE_STYLE_MAP.put(CommonCodeStyleSettings.END_OF_LINE, VALUE_END_OF_LINE);
- BRACE_STYLE_MAP.put(CommonCodeStyleSettings.NEXT_LINE, VALUE_NEXT_LINE);
- BRACE_STYLE_MAP.put(CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED, VALUE_NEXT_LINE_IF_WRAPPED);
- BRACE_STYLE_MAP.put(CommonCodeStyleSettings.NEXT_LINE_SHIFTED, VALUE_WHITESMITHS);
- BRACE_STYLE_MAP.put(CommonCodeStyleSettings.NEXT_LINE_SHIFTED2, VALUE_GNU);
- }
+class BraceStyleAccessor extends MagicIntegerConstAccessor {
BraceStyleAccessor(@NotNull Object object, @NotNull Field field) {
- super(object, field);
+ super(object,
+ field,
+ new int[]{
+ CommonCodeStyleSettings.END_OF_LINE,
+ CommonCodeStyleSettings.NEXT_LINE,
+ CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED,
+ CommonCodeStyleSettings.NEXT_LINE_SHIFTED,
+ CommonCodeStyleSettings.NEXT_LINE_SHIFTED2
+ },
+ new String[]{
+ "end_of_line",
+ "next_line",
+ "next_line_if_wrapped",
+ "whitesmiths",
+ "gnu"
+ });
}
- @Nullable
- @Override
- protected Integer fromExternal(@NotNull String str) {
- List keys = BRACE_STYLE_MAP.getKeysByValue(str);
- return keys != null && keys.size() > 0 ? keys.get(0) : null;
- }
-
- @NotNull
- @Override
- protected String toExternal(@NotNull Integer value) {
- return BRACE_STYLE_MAP.get(value);
- }
-
- @NotNull
- @Override
- public List getChoices() {
- return ALL_VALUES;
- }
}
diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/FieldAccessorFactory.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/FieldAccessorFactory.java
index 6d0dd2601894..fd693d735f00 100644
--- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/FieldAccessorFactory.java
+++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/FieldAccessorFactory.java
@@ -1,6 +1,7 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.application.options.codeStyle.properties;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings.BraceStyleConstant;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings.WrapConstant;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,7 +37,8 @@ class FieldAccessorFactory {
if (wrapAnnotation != null) {
return ValueType.WRAP;
}
- else if (fieldName.endsWith("BRACE_STYLE")) {
+ BraceStyleConstant braceAnnotation = myField.getAnnotation(BraceStyleConstant.class);
+ if (braceAnnotation != null) {
return ValueType.BRACE_STYLE;
}
else if (fieldName.endsWith("_BRACE_FORCE")) {
diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/ForceBracesAccessor.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/ForceBracesAccessor.java
index 73c07c7e4e24..f4ce69982cf2 100644
--- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/ForceBracesAccessor.java
+++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/ForceBracesAccessor.java
@@ -2,50 +2,24 @@
package com.intellij.application.options.codeStyle.properties;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
-import com.intellij.util.containers.BidirectionalMap;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.List;
-class ForceBracesAccessor extends ExternalStringAccessor implements CodeStyleChoiceList {
-
- private final static BidirectionalMap FORCE_BRACES_MAP = new BidirectionalMap<>();
-
- public static final String VALUE_NEVER = "never";
- public static final String VALUE_MULTILINE = "if_multiline";
- public static final String VALUE_ALWAYS = "always";
-
- private final static List ALL_VALUES = Arrays.asList(VALUE_NEVER, VALUE_MULTILINE, VALUE_ALWAYS);
-
- static {
- FORCE_BRACES_MAP.put(CommonCodeStyleSettings.DO_NOT_FORCE, VALUE_NEVER);
- FORCE_BRACES_MAP.put(CommonCodeStyleSettings.FORCE_BRACES_IF_MULTILINE, VALUE_MULTILINE);
- FORCE_BRACES_MAP.put(CommonCodeStyleSettings.FORCE_BRACES_ALWAYS, VALUE_ALWAYS);
- }
+class ForceBracesAccessor extends MagicIntegerConstAccessor {
ForceBracesAccessor(@NotNull Object object, @NotNull Field field) {
- super(object, field);
- }
-
- @Nullable
- @Override
- protected Integer fromExternal(@NotNull String str) {
- List keys = FORCE_BRACES_MAP.getKeysByValue(str);
- return keys != null && keys.size() > 0 ? keys.get(0) : null;
- }
-
- @NotNull
- @Override
- protected String toExternal(@NotNull Integer value) {
- return FORCE_BRACES_MAP.get(value);
- }
-
- @NotNull
- @Override
- public List getChoices() {
- return ALL_VALUES;
+ super(object,
+ field,
+ new int[]{
+ CommonCodeStyleSettings.DO_NOT_FORCE,
+ CommonCodeStyleSettings.FORCE_BRACES_IF_MULTILINE,
+ CommonCodeStyleSettings.FORCE_BRACES_ALWAYS
+ },
+ new String[]{
+ "never",
+ "if_multiline",
+ "always"
+ });
}
}
diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/MagicIntegerConstAccessor.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/MagicIntegerConstAccessor.java
new file mode 100644
index 000000000000..058e4de6ba28
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/MagicIntegerConstAccessor.java
@@ -0,0 +1,43 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.application.options.codeStyle.properties;
+
+import com.intellij.util.containers.BidirectionalMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MagicIntegerConstAccessor extends ExternalStringAccessor implements CodeStyleChoiceList {
+ private final BidirectionalMap myValueMap = new BidirectionalMap<>();
+
+ public MagicIntegerConstAccessor(@NotNull Object object,
+ @NotNull Field field,
+ int[] intValues,
+ String[] strValues) {
+ super(object, field);
+ for (int i = 0; i < Math.min(intValues.length, strValues.length); i ++) {
+ myValueMap.put(intValues[i], strValues[i]);
+ }
+ }
+
+ @Nullable
+ @Override
+ protected final Integer fromExternal(@NotNull String str) {
+ List keys = myValueMap.getKeysByValue(str);
+ return keys != null && keys.size() > 0 ? keys.get(0) : null;
+ }
+
+ @NotNull
+ @Override
+ protected final String toExternal(@NotNull Integer value) {
+ return myValueMap.get(value);
+ }
+
+ @NotNull
+ @Override
+ public final List getChoices() {
+ return new ArrayList<>(myValueMap.values());
+ }
+}
diff --git a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/WrappingAccessor.java b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/WrappingAccessor.java
index 5b36127b0d7d..9dfd58cd9d0c 100644
--- a/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/WrappingAccessor.java
+++ b/platform/lang-api/src/com/intellij/application/options/codeStyle/properties/WrappingAccessor.java
@@ -2,53 +2,28 @@
package com.intellij.application.options.codeStyle.properties;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
-import com.intellij.util.containers.BidirectionalMap;
-import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
-import java.util.List;
-class WrappingAccessor extends ExternalStringAccessor implements CodeStyleChoiceList {
- private final static BidirectionalMap WRAPPING_MAP = new BidirectionalMap<>();
-
- public static final String VALUE_OFF = "off";
- public static final String VALUE_NORMAL = "normal";
- public static final String VALUE_ON_EVERY_ITEM = "on_every_item";
- public static final String VALUE_SPLIT_INTO_LINES = "split_into_lines";
-
- public final static List ALL_VALUES =
- ContainerUtil.immutableList(VALUE_OFF, VALUE_NORMAL, VALUE_ON_EVERY_ITEM, VALUE_SPLIT_INTO_LINES);
-
- static {
- WRAPPING_MAP.put(CommonCodeStyleSettings.DO_NOT_WRAP, VALUE_OFF);
- WRAPPING_MAP.put(CommonCodeStyleSettings.WRAP_AS_NEEDED, VALUE_NORMAL);
- WRAPPING_MAP.put(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, VALUE_ON_EVERY_ITEM);
- WRAPPING_MAP.put(CommonCodeStyleSettings.WRAP_AS_NEEDED | CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, VALUE_ON_EVERY_ITEM);
- WRAPPING_MAP.put(CommonCodeStyleSettings.WRAP_ALWAYS, VALUE_SPLIT_INTO_LINES);
- }
+class WrappingAccessor extends MagicIntegerConstAccessor {
WrappingAccessor(@NotNull Object object, @NotNull Field field) {
- super(object, field);
+ super(object, field,
+ new int[]{
+ CommonCodeStyleSettings.DO_NOT_WRAP,
+ CommonCodeStyleSettings.WRAP_AS_NEEDED,
+ CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM,
+ CommonCodeStyleSettings.WRAP_AS_NEEDED | CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM,
+ CommonCodeStyleSettings.WRAP_ALWAYS
+ },
+ new String[]{
+ "off",
+ "normal",
+ "on_every_item",
+ "on_every_item",
+ "split_into_lines",
+ });
}
- @Nullable
- @Override
- protected Integer fromExternal(@NotNull String str) {
- List keys = WRAPPING_MAP.getKeysByValue(str);
- return keys != null && keys.size() > 0 ? keys.get(0) : null;
- }
-
- @NotNull
- @Override
- protected String toExternal(@NotNull Integer value) {
- return WRAPPING_MAP.get(value);
- }
-
- @NotNull
- @Override
- public List getChoices() {
- return ALL_VALUES;
- }
}
diff --git a/platform/lang-api/src/com/intellij/build/output/BuildOutputInstantReader.java b/platform/lang-api/src/com/intellij/build/output/BuildOutputInstantReader.java
index 3c23241f76f9..ecec01938f91 100644
--- a/platform/lang-api/src/com/intellij/build/output/BuildOutputInstantReader.java
+++ b/platform/lang-api/src/com/intellij/build/output/BuildOutputInstantReader.java
@@ -2,6 +2,7 @@
package com.intellij.build.output;
import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -9,7 +10,8 @@ import org.jetbrains.annotations.Nullable;
*/
@ApiStatus.Experimental
public interface BuildOutputInstantReader {
- Object getBuildId();
+ @NotNull
+ Object getParentEventId();
@Nullable
String readLine();
diff --git a/platform/lang-api/src/com/intellij/build/output/BuildOutputParser.java b/platform/lang-api/src/com/intellij/build/output/BuildOutputParser.java
index e624bbc0019a..242d5ff57640 100644
--- a/platform/lang-api/src/com/intellij/build/output/BuildOutputParser.java
+++ b/platform/lang-api/src/com/intellij/build/output/BuildOutputParser.java
@@ -2,7 +2,6 @@
package com.intellij.build.output;
import com.intellij.build.events.BuildEvent;
-import com.intellij.build.events.MessageEvent;
import org.jetbrains.annotations.ApiStatus;
import java.util.function.Consumer;
diff --git a/platform/lang-api/src/com/intellij/codeInsight/editorActions/TabOutScopesTracker.java b/platform/lang-api/src/com/intellij/codeInsight/editorActions/TabOutScopesTracker.java
index 814a69a3936a..9f61545f6ed7 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/editorActions/TabOutScopesTracker.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/editorActions/TabOutScopesTracker.java
@@ -3,7 +3,6 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.Editor;
-import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
@@ -11,7 +10,6 @@ import org.jetbrains.annotations.NotNull;
* quote/bracket) using Tab key. The scope is usually created (registered) when a pair of quotes/brackets is inserted into a document, and
* lives until user 'tabs out' of this scope, or performs editing outside it.
*/
-@ApiStatus.Experimental
public interface TabOutScopesTracker {
static TabOutScopesTracker getInstance() {
return ServiceManager.getService(TabOutScopesTracker.class);
@@ -29,7 +27,16 @@ public interface TabOutScopesTracker {
* Registers a new scope (empty at the time of call) at the given offset. Provided offset is supposed to point at the location between
* just inserted pair of quotes/brackets.
*/
- void registerEmptyScope(@NotNull Editor editor, int offset);
+ default void registerEmptyScope(@NotNull Editor editor, int offset) {
+ registerEmptyScope(editor, offset, 1);
+ }
+
+ /**
+ * Same as {@link #registerEmptyScope(Editor, int)} but allows to set custom caret shift on exiting the scope. This is for the cases when scope suffix contains more than one character (e.g. a closing parenthesis and a semicolon).
+ *
+ * @param caretShift a positive value, representing desired caret offset shift when Tab is used to exit the scope
+ */
+ void registerEmptyScope(@NotNull Editor editor, int offset, int caretShift);
/**
* Checks whether given offset is at the end of tracked scope (so if caret is located at that offset, Tab key can be used to move out of
@@ -40,9 +47,10 @@ public interface TabOutScopesTracker {
/**
* Removes a tracked scope (if any) ending at the given offset.
*
- * @return whether there was a scope ending at given offset
+ * @return a positive value indicating required caret shift, if there was a scope ending at given offset, and zero otherwise
*
* @see #hasScopeEndingAt(Editor, int)
+ * @see #registerEmptyScope(Editor, int, int)
*/
- boolean removeScopeEndingAt(@NotNull Editor editor, int offset);
+ int removeScopeEndingAt(@NotNull Editor editor, int offset);
}
diff --git a/platform/lang-api/src/com/intellij/formatting/Block.java b/platform/lang-api/src/com/intellij/formatting/Block.java
index a8955603acc7..f4834d8658cc 100644
--- a/platform/lang-api/src/com/intellij/formatting/Block.java
+++ b/platform/lang-api/src/com/intellij/formatting/Block.java
@@ -39,6 +39,8 @@ public interface Block {
* Returns the list of child blocks for the specified block. Important: The same list
* of blocks must be returned when {@code getSubBlocks()} is repeatedly called on a particular
* {@code Block} instance.
+ * Even more Important:
+ * If immutable list is returned (e.g. {@code Collections.singletonList(xxx)}, you must mark this {@link Block} class with {@link com.intellij.formatting.ReadOnlyBlockContainer} marker interface.
*
* @return the child block list.
* @see #isLeaf()
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
index 59baf1d091d3..01271fd9a585 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
@@ -331,6 +331,7 @@ public class CommonCodeStyleSettings {
public static final int NEXT_LINE_IF_WRAPPED = 5;
@MagicConstant(intValues = {END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_SHIFTED2, NEXT_LINE_IF_WRAPPED})
+ @Retention(RetentionPolicy.RUNTIME)
public @interface BraceStyleConstant {}
@BraceStyleConstant public int BRACE_STYLE = END_OF_LINE;
diff --git a/platform/lang-impl/src/com/intellij/build/output/BuildOutputInstantReaderImpl.kt b/platform/lang-impl/src/com/intellij/build/output/BuildOutputInstantReaderImpl.kt
index 86f7f247aac5..b0319db33570 100644
--- a/platform/lang-impl/src/com/intellij/build/output/BuildOutputInstantReaderImpl.kt
+++ b/platform/lang-impl/src/com/intellij/build/output/BuildOutputInstantReaderImpl.kt
@@ -17,7 +17,7 @@ import java.util.concurrent.Future
/**
* @author Vladislav.Soroka
*/
-open class BuildOutputInstantReaderImpl(private val buildId: Any,
+open class BuildOutputInstantReaderImpl(private val parentEventId: Any,
buildProgressListener: BuildProgressListener,
parsers: List) : BuildOutputInstantReader, Closeable, Appendable {
private val readJob: Job
@@ -29,14 +29,14 @@ open class BuildOutputInstantReaderImpl(private val buildId: Any,
private val appendedLineProcessor: LineProcessor
init {
- readJob = createReadJob(buildProgressListener, this, parsers)
+ readJob = createReadJob(buildProgressListener, parsers)
val appendScope = CoroutineScope(Dispatchers.Default + appendParentJob)
appendedLineProcessor = MyLineProcessor(readJob, appendScope, outputLinesChannel)
}
private fun createReadJob(buildProgressListener: BuildProgressListener,
- reader: BuildOutputInstantReaderImpl,
parsers: List): Job {
+ val thisReader: BuildOutputInstantReader = this
return CoroutineScope(Dispatchers.Default).launch(start = CoroutineStart.LAZY) {
var lastMessage: BuildEvent? = null
val messageConsumer = { event: BuildEvent ->
@@ -48,11 +48,11 @@ open class BuildOutputInstantReaderImpl(private val buildId: Any,
}
while (true) {
- val line = reader.readLine() ?: break
+ val line = thisReader.readLine() ?: break
if (line.isBlank()) continue
for (parser in parsers) {
- val readerWrapper = BuildOutputInstantReaderWrapper(reader)
+ val readerWrapper = BuildOutputInstantReaderWrapper(thisReader)
if (parser.parse(line, readerWrapper, messageConsumer)) break
readerWrapper.pushBackReadLines()
}
@@ -60,8 +60,8 @@ open class BuildOutputInstantReaderImpl(private val buildId: Any,
}
}
- override fun getBuildId(): Any {
- return buildId
+ override fun getParentEventId(): Any {
+ return parentEventId
}
override fun append(csq: CharSequence): BuildOutputInstantReaderImpl {
@@ -146,10 +146,10 @@ open class BuildOutputInstantReaderImpl(private val buildId: Any,
}
}
- private class BuildOutputInstantReaderWrapper(private val reader: BuildOutputInstantReaderImpl) : BuildOutputInstantReader {
+ private class BuildOutputInstantReaderWrapper(private val reader: BuildOutputInstantReader) : BuildOutputInstantReader {
private var linesRead = 0
- override fun getBuildId(): Any = reader.buildId
+ override fun getParentEventId(): Any = reader.parentEventId
override fun readLine(): String? {
val line = reader.readLine()
diff --git a/java/compiler/impl/src/com/intellij/build/output/JavacOutputParser.java b/platform/lang-impl/src/com/intellij/build/output/JavacOutputParser.java
similarity index 90%
rename from java/compiler/impl/src/com/intellij/build/output/JavacOutputParser.java
rename to platform/lang-impl/src/com/intellij/build/output/JavacOutputParser.java
index 52052ef7dc62..94bd72e05856 100644
--- a/java/compiler/impl/src/com/intellij/build/output/JavacOutputParser.java
+++ b/platform/lang-impl/src/com/intellij/build/output/JavacOutputParser.java
@@ -39,17 +39,17 @@ public class JavacOutputParser implements BuildOutputParser {
if (part1.equalsIgnoreCase("error") /* jikes */ || part1.equalsIgnoreCase("Caused by")) {
// +1 so we don't include the colon
String text = line.substring(colonIndex1 + 1).trim();
- messageConsumer.accept(new MessageEventImpl(reader.getBuildId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, text, line));
+ messageConsumer.accept(new MessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, text, line));
return true;
}
if (part1.equalsIgnoreCase("warning")) {
// +1 so we don't include the colon
String text = line.substring(colonIndex1 + 1).trim();
- messageConsumer.accept(new MessageEventImpl(reader.getBuildId(), MessageEvent.Kind.WARNING, COMPILER_MESSAGES_GROUP, text, line));
+ messageConsumer.accept(new MessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.WARNING, COMPILER_MESSAGES_GROUP, text, line));
return true;
}
if (part1.equalsIgnoreCase("javac")) {
- messageConsumer.accept(new MessageEventImpl(reader.getBuildId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, line, line));
+ messageConsumer.accept(new MessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, line, line));
return true;
}
if (part1.equalsIgnoreCase("Note")) {
@@ -60,7 +60,7 @@ public class JavacOutputParser implements BuildOutputParser {
if (file.isFile()) {
message = message.substring(javaFileExtensionIndex + ".java".length() + 1);
String detailedMessage = amendNextInfoLinesIfNeeded(file.getPath() + ":\n" + message, reader);
- messageConsumer.accept(new FileMessageEventImpl(reader.getBuildId(), MessageEvent.Kind.INFO, COMPILER_MESSAGES_GROUP,
+ messageConsumer.accept(new FileMessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.INFO, COMPILER_MESSAGES_GROUP,
message, detailedMessage,
new FilePosition(file, 0, 0)));
return true;
@@ -124,7 +124,7 @@ public class JavacOutputParser implements BuildOutputParser {
if (column >= 0) {
messageList = convertMessages(messageList);
String msgText = StringUtil.join(messageList, SystemProperties.getLineSeparator());
- messageConsumer.accept(new FileMessageEventImpl(reader.getBuildId(), kind, COMPILER_MESSAGES_GROUP, msgText, msgText,
+ messageConsumer.accept(new FileMessageEventImpl(reader.getParentEventId(), kind, COMPILER_MESSAGES_GROUP, msgText, msgText,
new FilePosition(file, lineNumber - 1, column)));
return true;
}
@@ -135,7 +135,7 @@ public class JavacOutputParser implements BuildOutputParser {
}
if (line.endsWith("java.lang.OutOfMemoryError")) {
- messageConsumer.accept(new MessageEventImpl(reader.getBuildId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP,
+ messageConsumer.accept(new MessageEventImpl(reader.getParentEventId(), MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP,
"Out of memory.", line));
return true;
}
diff --git a/java/compiler/impl/src/com/intellij/build/output/KotlincOutputParser.kt b/platform/lang-impl/src/com/intellij/build/output/KotlincOutputParser.kt
similarity index 85%
rename from java/compiler/impl/src/com/intellij/build/output/KotlincOutputParser.kt
rename to platform/lang-impl/src/com/intellij/build/output/KotlincOutputParser.kt
index 3c85188eba28..b694a1c072c5 100644
--- a/java/compiler/impl/src/com/intellij/build/output/KotlincOutputParser.kt
+++ b/platform/lang-impl/src/com/intellij/build/output/KotlincOutputParser.kt
@@ -1,4 +1,4 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.build.output
import com.intellij.build.FilePosition
@@ -37,7 +37,7 @@ class KotlincOutputParser : BuildOutputParser {
val fileExtension = file.extension.toLowerCase()
if (!file.isFile || (fileExtension != "kt" && fileExtension != "java")) {
- return addMessage(createMessage(reader.buildId, getMessageKind(severity), lineWoSeverity.amendNextLinesIfNeeded(reader), line),
+ return addMessage(createMessage(reader.parentEventId, getMessageKind(severity), lineWoSeverity.amendNextLinesIfNeeded(reader), line),
consumer)
}
@@ -57,15 +57,15 @@ class KotlincOutputParser : BuildOutputParser {
if (lineNumber != null) {
val symbolNumberText = symbolNumber.toInt()
return addMessage(createMessageWithLocation(
- reader.buildId, getMessageKind(severity), message, path, lineNumber.toInt(), symbolNumberText, details), consumer)
+ reader.parentEventId, getMessageKind(severity), message, path, lineNumber.toInt(), symbolNumberText, details), consumer)
}
}
- return addMessage(createMessage(reader.buildId, getMessageKind(severity), message, details), consumer)
+ return addMessage(createMessage(reader.parentEventId, getMessageKind(severity), message, details), consumer)
}
else {
val text = lineWoSeverity.amendNextLinesIfNeeded(reader)
- return addMessage(createMessage(reader.buildId, getMessageKind(severity), text, text), consumer)
+ return addMessage(createMessage(reader.parentEventId, getMessageKind(severity), text, text), consumer)
}
}
@@ -139,12 +139,12 @@ class KotlincOutputParser : BuildOutputParser {
return true
}
- private fun createMessage(buildId: Any, messageKind: MessageEvent.Kind, text: String, detail: String): MessageEvent {
- return MessageEventImpl(buildId, messageKind, COMPILER_MESSAGES_GROUP, text.trim(), detail)
+ private fun createMessage(parentId: Any, messageKind: MessageEvent.Kind, text: String, detail: String): MessageEvent {
+ return MessageEventImpl(parentId, messageKind, COMPILER_MESSAGES_GROUP, text.trim(), detail)
}
private fun createMessageWithLocation(
- buildId: Any,
+ parentId: Any,
messageKind: MessageEvent.Kind,
text: String,
file: String,
@@ -152,7 +152,7 @@ class KotlincOutputParser : BuildOutputParser {
columnIndex: Int,
detail: String
): FileMessageEventImpl {
- return FileMessageEventImpl(buildId, messageKind, COMPILER_MESSAGES_GROUP, text.trim(), detail,
+ return FileMessageEventImpl(parentId, messageKind, COMPILER_MESSAGES_GROUP, text.trim(), detail,
FilePosition(File(file), lineNumber - 1, columnIndex - 1))
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
index 0db7e4285de0..a77aec50a48e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
@@ -10,6 +10,7 @@ import com.intellij.icons.AllIcons;
import com.intellij.ide.DataManager;
import com.intellij.ide.actions.BaseNavigateToSourceAction;
import com.intellij.ide.actions.ExternalJavaDocAction;
+import com.intellij.ide.actions.WindowAction;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.lang.documentation.CompositeDocumentationProvider;
import com.intellij.lang.documentation.DocumentationMarkup;
@@ -17,11 +18,13 @@ import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.lang.documentation.ExternalDocumentationHandler;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ex.AnActionListener;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.actionSystem.impl.MenuItemPresentationFactory;
import com.intellij.openapi.application.ApplicationBundle;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.ColorKey;
import com.intellij.openapi.editor.colors.EditorColorsManager;
@@ -927,13 +930,21 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
AbstractPopup hint = myHint;
if (hint == null || mySizeTrackerRegistered) return;
mySizeTrackerRegistered = true;
- hint.addResizeListener(() -> {
- myManuallyResized = true;
- if (myStoreSize) {
- hint.setDimensionServiceKey(DocumentationManager.NEW_JAVADOC_LOCATION_AND_SIZE);
- hint.storeDimensionSize();
+ hint.addResizeListener(this::onManualResizing, this);
+ ApplicationManager.getApplication().getMessageBus().connect(this).subscribe(AnActionListener.TOPIC, new AnActionListener() {
+ @Override
+ public void afterActionPerformed(@NotNull AnAction action, @NotNull DataContext dataContext, @NotNull AnActionEvent event) {
+ if (action instanceof WindowAction) onManualResizing();
}
- }, this);
+ });
+ }
+
+ private void onManualResizing() {
+ myManuallyResized = true;
+ if (myStoreSize && myHint != null) {
+ myHint.setDimensionServiceKey(DocumentationManager.NEW_JAVADOC_LOCATION_AND_SIZE);
+ myHint.storeDimensionSize();
+ }
}
private int definitionPreferredWidth() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
index d5801d535783..40da18976ace 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
@@ -14,6 +14,7 @@ import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.actions.BaseNavigateToSourceAction;
+import com.intellij.ide.actions.WindowAction;
import com.intellij.ide.highlighter.ArchiveFileType;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.ide.util.gotoByName.ChooseByNameBase;
@@ -104,7 +105,8 @@ public class DocumentationManager extends DockablePopupManager CARET_SHIFT = Key.create("tab.out.caret.shift");
+
@Override
- public void registerEmptyScope(@NotNull Editor editor, int offset) {
+ public void registerEmptyScope(@NotNull Editor editor, int offset, int caretShift) {
ApplicationManager.getApplication().assertIsDispatchThread();
assert !editor.isDisposed() : "Disposed editor";
+ assert caretShift > 0 : "Caret shift must be positive";
if (!CodeInsightSettings.getInstance().TAB_EXITS_BRACKETS_AND_QUOTES) return;
@@ -37,35 +40,35 @@ public class TabOutScopesTrackerImpl implements TabOutScopesTracker {
if (!(editor instanceof EditorImpl)) return;
Tracker tracker = Tracker.forEditor((EditorImpl)editor, true);
- tracker.registerScope(offset);
+ tracker.registerScope(offset, caretShift);
}
@Override
public boolean hasScopeEndingAt(@NotNull Editor editor, int offset) {
- return checkOrRemoveScopeEndingAt(editor, offset, false);
+ return checkOrRemoveScopeEndingAt(editor, offset, false) > 0;
}
@Override
- public boolean removeScopeEndingAt(@NotNull Editor editor, int offset) {
+ public int removeScopeEndingAt(@NotNull Editor editor, int offset) {
return checkOrRemoveScopeEndingAt(editor, offset, true);
}
- private static boolean checkOrRemoveScopeEndingAt(@NotNull Editor editor, int offset, boolean removeScope) {
+ private static int checkOrRemoveScopeEndingAt(@NotNull Editor editor, int offset, boolean removeScope) {
ApplicationManager.getApplication().assertIsDispatchThread();
- if (!CodeInsightSettings.getInstance().TAB_EXITS_BRACKETS_AND_QUOTES) return false;
+ if (!CodeInsightSettings.getInstance().TAB_EXITS_BRACKETS_AND_QUOTES) return 0;
if (editor instanceof EditorWindow) {
DocumentWindow documentWindow = ((EditorWindow)editor).getDocument();
offset = documentWindow.injectedToHost(offset);
editor = ((EditorWindow)editor).getDelegate();
}
- if (!(editor instanceof EditorImpl)) return false;
+ if (!(editor instanceof EditorImpl)) return 0;
Tracker tracker = Tracker.forEditor((EditorImpl)editor, false);
- if (tracker == null) return false;
+ if (tracker == null) return 0;
- return tracker.hasScopeEndingAt(offset, removeScope);
+ return tracker.getCaretShiftForScopeEndingAt(offset, removeScope);
}
private static class Tracker extends DocumentBulkUpdateListener.Adapter implements DocumentListener {
@@ -98,24 +101,26 @@ public class TabOutScopesTrackerImpl implements TabOutScopesTracker {
return result;
}
- private void registerScope(int offset) {
+ private void registerScope(int offset, int caretShift) {
RangeMarker marker = myEditor.getDocument().createRangeMarker(offset, offset);
marker.setGreedyToLeft(true);
marker.setGreedyToRight(true);
+ if (caretShift > 1) marker.putUserData(CARET_SHIFT, caretShift);
getCurrentScopes(true).add(marker);
}
- private boolean hasScopeEndingAt(int offset, boolean remove) {
+ private int getCaretShiftForScopeEndingAt(int offset, boolean remove) {
List scopes = getCurrentScopes(false);
- if (scopes == null) return false;
+ if (scopes == null) return 0;
for (Iterator it = scopes.iterator(); it.hasNext(); ) {
RangeMarker scope = it.next();
if (offset == scope.getEndOffset()) {
if (remove) it.remove();
- return true;
+ Integer caretShift = scope.getUserData(CARET_SHIFT);
+ return caretShift == null ? 1 : caretShift;
}
}
- return false;
+ return 0;
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java
index 1969616f0c64..10cf42f351a0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java
@@ -305,7 +305,7 @@ public class TemplateImpl extends Template implements SchemeElement {
}
mySegments = new SmartList<>();
- StringBuilder buffer = new StringBuilder();
+ StringBuilder buffer = new StringBuilder(myString.length());
TemplateTextLexer lexer = new TemplateTextLexer();
lexer.start(myString);
diff --git a/platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiElementBase.java b/platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiElementBase.java
deleted file mode 100644
index be4b4424a805..000000000000
--- a/platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiElementBase.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2000-2009 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.extapi.psi;
-
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.NotNull;
-
-@Deprecated
-@ApiStatus.ScheduledForRemoval(inVersion = "2019.2")
-public abstract class MetadataPsiElementBase extends PsiElementBase {
-
- private final PsiElement mySourceElement;
-
- public MetadataPsiElementBase(PsiElement sourceElement) {
- mySourceElement = sourceElement;
- }
-
- @Override
- public TextRange getTextRange() {
- return mySourceElement != null? mySourceElement.getTextRange() : null;
- }
-
- @Override
- public int getStartOffsetInParent() {
- final PsiElement parent = getParent();
- return (parent == null) ? 0 : getTextRange().getStartOffset() - parent.getTextRange().getStartOffset();
- }
-
- @Override
- public int getTextLength() {
- return mySourceElement.getTextLength();
- }
-
- @Override
- public int getTextOffset() {
- return mySourceElement.getTextOffset();
- }
-
- @Override
- public String getText() {
- return mySourceElement.getText();
- }
-
- @Override
- @NotNull
- public char[] textToCharArray() {
- return mySourceElement.textToCharArray();
- }
-
- @Override
- public boolean textContains(char c) {
- return mySourceElement.textContains(c);
- }
-
- public PsiElement getSourceElement() {
- return mySourceElement;
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java b/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java
deleted file mode 100644
index 5eb81451d5d6..000000000000
--- a/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.intellij.extapi.psi;
-
-import com.intellij.ide.util.PsiNavigationSupport;
-import com.intellij.navigation.ItemPresentation;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.pom.Navigatable;
-import com.intellij.psi.*;
-import com.intellij.psi.impl.ElementBase;
-import com.intellij.psi.impl.ResolveScopeManager;
-import com.intellij.psi.impl.SharedPsiElementImplUtil;
-import com.intellij.psi.scope.PsiScopeProcessor;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.SearchScope;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @deprecated Please use {@link com.intellij.psi.impl.PsiElementBase} as a base class
- * or one of its descendants, e.g. {@link ASTWrapperPsiElement}, as suggested in a
- * tutorial
- */
-@Deprecated
-@ApiStatus.ScheduledForRemoval(inVersion = "2019.2")
-public abstract class PsiElementBase extends ElementBase implements NavigatablePsiElement {
- private static final Logger LOG = Logger.getInstance("#com.intellij.extapi.psi.PsiElementBase");
-
- @Override
- public PsiElement copy() {
- return (PsiElement)clone();
- }
-
- @Override
- public PsiElement add(@NotNull PsiElement element) throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public void checkAdd(@NotNull PsiElement element) throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public PsiElement addRange(PsiElement first, PsiElement last) throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public PsiElement addRangeBefore(@NotNull PsiElement first, @NotNull PsiElement last, PsiElement anchor) throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public PsiElement addRangeAfter(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public void delete() throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public void checkDelete() throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public void deleteChildRange(PsiElement first, PsiElement last) throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException {
- throw new UnsupportedOperationException(getClass().getName());
- }
-
- @Override
- public PsiReference getReference() {
- return null;
- }
-
- @Override
- public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) {
- return true;
- }
-
- @Override
- @NotNull
- public Project getProject() {
- final PsiManager manager = getManager();
- if (manager == null) {
- throw new PsiInvalidElementAccessException(this);
- }
-
- return manager.getProject();
- }
-
- @Override
- public PsiManager getManager() {
- final PsiElement parent = getParent();
- return parent != null ? parent.getManager() : null;
- }
-
- @Override
- public PsiFile getContainingFile() {
- final PsiElement parent = getParent();
- if (parent == null) throw new PsiInvalidElementAccessException(this);
- return parent.getContainingFile();
- }
-
- @Override
- public PsiReference findReferenceAt(int offset) {
- return SharedPsiElementImplUtil.findReferenceAt(this, offset);
- }
-
- @Override
- @NotNull
- public PsiElement getNavigationElement() {
- return this;
- }
-
- @Override
- public PsiElement getOriginalElement() {
- return this;
- }
-
- //Q: get rid of these methods?
- @Override
- public boolean textMatches(@NotNull CharSequence text) {
- return Comparing.equal(getText(), text, true);
- }
-
- @Override
- public boolean textMatches(@NotNull PsiElement element) {
- return getText().equals(element.getText());
- }
-
- @Override
- public void accept(@NotNull PsiElementVisitor visitor) {
- visitor.visitElement(this);
- }
-
- @Override
- public void acceptChildren(@NotNull PsiElementVisitor visitor) {
- PsiElement child = getFirstChild();
- while (child != null) {
- child.accept(visitor);
- child = child.getNextSibling();
- }
- }
-
- @Override
- public boolean isValid() {
- final PsiElement parent = getParent();
- return parent != null && parent.isValid();
- }
-
- @Override
- public boolean isWritable() {
- final PsiElement parent = getParent();
- return parent != null && parent.isWritable();
- }
-
- @Override
- @NotNull
- public PsiReference[] getReferences() {
- return SharedPsiElementImplUtil.getReferences(this);
- }
-
- @Override
- public PsiElement getContext() {
- return getParent();
- }
-
- @Override
- public boolean isPhysical() {
- final PsiElement parent = getParent();
- return parent != null && parent.isPhysical();
- }
-
- @Override
- @NotNull
- public GlobalSearchScope getResolveScope() {
- return ResolveScopeManager.getElementResolveScope(this);
- }
-
- @Override
- @NotNull
- public SearchScope getUseScope() {
- return ResolveScopeManager.getElementUseScope(this);
- }
-
- /**
- * Returns the UI presentation data for the PSI element.
- *
- * @return null, unless overridden in a subclass.
- */
- @Override
- public ItemPresentation getPresentation() {
- return null;
- }
-
- @Override
- public String getName() {
- return null;
- }
-
- @Override
- public void navigate(boolean requestFocus) {
- final Navigatable descriptor = PsiNavigationSupport.getInstance().getDescriptor(this);
- if (descriptor != null) descriptor.navigate(requestFocus);
- }
-
- @Override
- public boolean canNavigate() {
- return true;
- }
-
- @Override
- public boolean canNavigateToSource() {
- final Navigatable descriptor = PsiNavigationSupport.getInstance().getDescriptor(this);
- return descriptor != null && descriptor.canNavigateToSource();
- }
-
- @NotNull
- protected T[] findChildrenByClass(Class aClass) {
- List result = new ArrayList<>();
- for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (aClass.isInstance(cur)) result.add((T)cur);
- }
- return result.toArray(ArrayUtil.newArray(aClass, result.size()));
- }
-
- @Nullable
- protected T findChildByClass(Class aClass) {
- for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (aClass.isInstance(cur)) return (T)cur;
- }
- return null;
- }
-
- @NotNull
- protected T findNotNullChildByClass(Class aClass) {
- return notNullChild(findChildByClass(aClass));
- }
-
- @NotNull
- protected T notNullChild(T child) {
- if (child == null) {
- LOG.error(getText() + "\n parent=" + getParent().getText());
- }
- return child;
- }
-
- @Override
- public boolean isEquivalentTo(final PsiElement another) {
- return this == another;
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java
index 5b7c95f66247..67a2d2e54f23 100644
--- a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java
+++ b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java
@@ -17,6 +17,8 @@
package com.intellij.formatting;
import com.intellij.formatting.engine.ExpandableIndent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.codeStyle.CodeStyleSettings;
@@ -38,6 +40,7 @@ import java.util.Set;
* The main idea of block wrapping is to associate information about {@link WhiteSpace white space before block} with the block itself.
*/
public class InitialInfoBuilder {
+ private static final Logger LOG = Logger.getInstance(InitialInfoBuilder.class);
private static final RangesAssert ASSERT = new RangesAssert();
private static final boolean INLINE_TABS_ENABLED = "true".equalsIgnoreCase(System.getProperty("inline.tabs.enabled"));
@@ -46,7 +49,7 @@ public class InitialInfoBuilder {
private final MultiMap myBlocksToAlign = new MultiMap<>();
private final Set myAlignmentsInsideRangeToModify = ContainerUtil.newHashSet();
- private boolean myCollectAlignmentsInsideFormattingRange = false;
+ private boolean myCollectAlignmentsInsideFormattingRange;
private final FormattingDocumentModel myModel;
private final FormatTextRanges myAffectedRanges;
@@ -88,14 +91,14 @@ public class InitialInfoBuilder {
myFormatterTagHandler = new FormatterTagHandler(settings);
}
- protected static InitialInfoBuilder prepareToBuildBlocksSequentially(
- Block root,
- FormattingDocumentModel model,
- FormatProcessor.FormatOptions formatOptions,
- CodeStyleSettings settings,
- CommonCodeStyleSettings.IndentOptions options,
- @NotNull FormattingProgressCallback progressCallback)
- {
+ @NotNull
+ static InitialInfoBuilder prepareToBuildBlocksSequentially(
+ Block root,
+ FormattingDocumentModel model,
+ FormatProcessor.FormatOptions formatOptions,
+ CodeStyleSettings settings,
+ CommonCodeStyleSettings.IndentOptions options,
+ @NotNull FormattingProgressCallback progressCallback) {
InitialInfoBuilder builder = new InitialInfoBuilder(root, model, formatOptions.myAffectedRanges, settings, options, formatOptions.myInterestingOffset, progressCallback);
builder.setCollectAlignmentsInsideFormattingRange(formatOptions.myReformatContext);
builder.buildFrom(root, 0, null, null, null);
@@ -273,8 +276,24 @@ public class InitialInfoBuilder {
if (!state.readOnly) {
try {
subBlocks.set(currentBlockIndex, null); // to prevent extra strong refs during model building
- } catch (Throwable ex) {
- // read-only blocks
+ }
+ catch (Throwable ex) {
+ // todo fix kotlin
+ if ("org.jetbrains.kotlin.idea.formatter.KotlinBlock".equals(currentRoot.getClass().getName())) {
+ // ignore
+ }
+ else {
+ // read-only blocks
+ String msg = "Unable to null elements of list I got from getSubBlocks(): " + subBlocks.getClass() +
+ ". If you really want to return immutable list, please mark " + currentRoot.getClass() +
+ " with 'ReadOnlyBlockContainer' interface";
+ if (ApplicationManager.getApplication().isInternal() || ApplicationManager.getApplication().isUnitTestMode()) {
+ LOG.error(msg, ex);
+ }
+ else {
+ LOG.warn(msg, ex);
+ }
+ }
}
}
diff --git a/platform/lang-impl/src/com/intellij/formatting/contextConfiguration/ConfigureCodeStyleOnSelectedFragment.java b/platform/lang-impl/src/com/intellij/formatting/contextConfiguration/ConfigureCodeStyleOnSelectedFragment.java
index 855007f8d9e2..1a6a67ed54c9 100644
--- a/platform/lang-impl/src/com/intellij/formatting/contextConfiguration/ConfigureCodeStyleOnSelectedFragment.java
+++ b/platform/lang-impl/src/com/intellij/formatting/contextConfiguration/ConfigureCodeStyleOnSelectedFragment.java
@@ -34,6 +34,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsCodeFragmentFilter;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.util.IncorrectOperationException;
@@ -177,6 +178,7 @@ public class ConfigureCodeStyleOnSelectedFragment implements IntentionAction, Lo
private void applyFromUiToSettings() {
try {
myTabbedLanguagePanel.apply(mySettings);
+ CodeStyleSettingsManager.getInstance(myEditor.getProject()).notifyCodeStyleSettingsChanged();
}
catch (ConfigurationException e) {
LOG.debug("Can not apply code style settings from context menu to project code style settings");
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java
index 8eb2deec3c6c..afff5bd296b0 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java
@@ -114,7 +114,7 @@ public class GotoFileItemProvider extends DefaultChooseByNameItemProvider {
* Invoke contributors directly, as multi-threading isn't of much value in Goto File,
* and filling {@link ContributorsBasedGotoByModel#myContributorToItsSymbolsMap} is expensive for the default contributor.
*/
- private void processNames(Processor nameProcessor) {
+ private void processNames(Processor super String> nameProcessor) {
List contributors = DumbService.getDumbAwareExtensions(myProject, ChooseByNameContributor.FILE_EP_NAME);
for (ChooseByNameContributor contributor : contributors) {
if (contributor instanceof DefaultFileNavigationContributor) {
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/newclass/CreateWithTemplatesDialogPanel.java b/platform/lang-impl/src/com/intellij/ide/actions/newclass/CreateWithTemplatesDialogPanel.java
index e79d18e6354e..9897166996ce 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/newclass/CreateWithTemplatesDialogPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/newclass/CreateWithTemplatesDialogPanel.java
@@ -10,13 +10,15 @@ import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Trinity;
import com.intellij.ui.DocumentAdapter;
-import com.intellij.ui.JBColor;
import com.intellij.ui.ScrollingUtil;
import com.intellij.ui.SimpleListCellRenderer;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBPanel;
+import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.components.JBTextField;
+import com.intellij.ui.components.fields.ExtendableTextComponent;
+import com.intellij.ui.components.fields.ExtendableTextField;
import com.intellij.util.BooleanFunction;
import com.intellij.util.Consumer;
import com.intellij.util.ui.JBUI;
@@ -34,7 +36,7 @@ import static com.intellij.ide.ui.laf.darcula.DarculaUIUtil.Outline;
public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposable {
- private final JBTextField myNameField;
+ private final ExtendableTextField myNameField;
private final JList> myTemplatesList;
private JBPopup myErrorPopup;
@@ -44,6 +46,7 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl
public CreateWithTemplatesDialogPanel(@NotNull List> templates, @Nullable String selectedItem) {
super(new BorderLayout());
+ setBackground(JBUI.CurrentTheme.NewClassDialog.panelBackground());
myNameField = createNameField();
myTemplatesList = createTemplatesList(templates);
@@ -54,7 +57,14 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl
selectTemplate(selectedItem);
add(myNameField, BorderLayout.NORTH);
- add(myTemplatesList, BorderLayout.CENTER);
+
+ JBScrollPane scrollPane = new JBScrollPane(myTemplatesList);
+ scrollPane.setBorder(JBUI.Borders.empty());
+ scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
+ Box listHolder = new Box(BoxLayout.Y_AXIS);
+ listHolder.setBorder(JBUI.Borders.emptyTop(JBUI.CurrentTheme.NewClassDialog.fieldsSeparatorWidth()));
+ listHolder.add(scrollPane);
+ add(listHolder, BorderLayout.CENTER);
}
public JTextField getNameField() {
@@ -100,8 +110,8 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl
}
@NotNull
- private JBTextField createNameField() {
- JBTextField res = new JBTextField();
+ private ExtendableTextField createNameField() {
+ ExtendableTextField res = new ExtendableTextField();
Dimension minSize = res.getMinimumSize();
Dimension prefSize = res.getPreferredSize();
@@ -111,13 +121,10 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl
res.setPreferredSize(prefSize);
res.setColumns(30);
- JBColor borderColor = JBColor.namedColor(
- "TextField.borderColor",
- JBColor.namedColor("Component.borderColor", new JBColor(0xbdbdbd, 0x646464))
- );
- Border border = JBUI.Borders.customLine(borderColor, 1, 0, 1, 0);
+ Border border = JBUI.Borders.customLine(JBUI.CurrentTheme.NewClassDialog.bordersColor(), 1, 0, 1, 0);
Border errorBorder = new ErrorBorder(res.getBorder());
res.setBorder(JBUI.Borders.merge(border, errorBorder, false));
+ res.setBackground(JBUI.CurrentTheme.NewClassDialog.searchFieldBackground());
res.putClientProperty("StatusVisibleFunction", (BooleanFunction) field -> field.getText().isEmpty());
res.getEmptyText().setText(IdeBundle.message("action.create.new.class.name.field"));
@@ -144,38 +151,38 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl
private JBList> createTemplatesList(@NotNull List> templates) {
JBList> list = new JBList<>(templates);
MouseAdapter mouseListener = new MouseAdapter() {
- // to avoid selection item under mouse when dialog appears (IDEA-209879)
- private boolean isFirstEvent = true;
-
- @Override
- public void mouseMoved(MouseEvent e) {
- if (isFirstEvent) {
- isFirstEvent = false;
- return;
- }
- selectItem(e.getPoint());
- }
-
@Override
public void mouseClicked(MouseEvent e) {
- selectItem(e.getPoint());
- if (myApplyAction != null) myApplyAction.consume(e);
- }
-
- private void selectItem(Point point) {
- int index = list.locationToIndex(point);
- if (index >= 0) {
- list.setSelectedIndex(index);
- }
+ if (myApplyAction != null && e.getClickCount() > 1) myApplyAction.consume(e);
}
};
- list.addMouseMotionListener(mouseListener);
+
list.addMouseListener(mouseListener);
list.setCellRenderer(LIST_RENDERER);
list.setFocusable(false);
+ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+ list.addListSelectionListener(e -> {
+ Trinity selectedValue = list.getSelectedValue();
+ if (selectedValue != null) {
+ setTextFieldIcon(selectedValue.second);
+ }
+ });
+
+ Border border = JBUI.Borders.merge(
+ JBUI.Borders.emptyLeft(JBUI.scale(5)),
+ JBUI.Borders.customLine(JBUI.CurrentTheme.NewClassDialog.bordersColor(), 1, 0, 0, 0),
+ true
+ );
+ list.setBorder(border);
return list;
}
+ private void setTextFieldIcon(Icon icon) {
+ myNameField.setExtensions(new TemplateIconExtension(icon));
+ myNameField.repaint();
+ }
+
private void selectTemplate(@Nullable String selectedItem) {
if (selectedItem == null) {
myTemplatesList.setSelectedIndex(0);
@@ -215,6 +222,22 @@ public class CreateWithTemplatesDialogPanel extends JBPanel implements Disposabl
}
};
+ private static class TemplateIconExtension implements ExtendableTextComponent.Extension {
+ private final Icon icon;
+
+ private TemplateIconExtension(Icon icon) {this.icon = icon;}
+
+ @Override
+ public Icon getIcon(boolean hovered) {
+ return icon;
+ }
+
+ @Override
+ public boolean isIconBeforeText() {
+ return true;
+ }
+ }
+
private static class ErrorBorder implements Border {
private final Border errorDelegateBorder;
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java
index 991b90ad6482..2247f2bd88f7 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java
@@ -76,15 +76,16 @@ public abstract class AbstractGotoSEContributor implements SearchEverywh
@NotNull Processor super Object> consumer) {
if (myProject == null) return; //nothing to search
if (!isEmptyPatternSupported() && pattern.isEmpty()) return;
- if (!isDumbModeSupported() && DumbService.getInstance(myProject).isDumb()) return;
-
- FilteringGotoByModel model = createModel(myProject);
- if (filter != null) {
- model.setFilterItems(filter.getSelectedElements());
- }
ProgressIndicatorUtils.yieldToPendingWriteActions();
ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(() -> {
+ if (!isDumbModeSupported() && DumbService.getInstance(myProject).isDumb()) return;
+
+ FilteringGotoByModel model = createModel(myProject);
+ if (filter != null) {
+ model.setFilterItems(filter.getSelectedElements());
+ }
+
if (progressIndicator.isCanceled()) return;
PsiElement context = psiContext != null && psiContext.isValid() ? psiContext : null;
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java
index da5a4db7c248..513f68a37618 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java
@@ -60,8 +60,6 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModelE
}
private final ConcurrentMap myContributorToItsSymbolsMap = ContainerUtil.newConcurrentMap();
- private volatile IdFilter myIdFilter;
- private volatile boolean myIdFilterForLibraries;
@Override
public void processNames(final Processor super String> nameProcessor, final boolean checkBoxState) {
@@ -125,14 +123,7 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModelE
}
IdFilter getIdFilter(boolean withLibraries) {
- IdFilter idFilter = myIdFilter;
-
- if (idFilter == null || myIdFilterForLibraries != withLibraries) {
- idFilter = IdFilter.getProjectIdFilter(myProject, withLibraries);
- myIdFilter = idFilter;
- myIdFilterForLibraries = withLibraries;
- }
- return idFilter;
+ return IdFilter.getProjectIdFilter(myProject, withLibraries);
}
@NotNull
diff --git a/platform/lang-impl/src/com/intellij/psi/search/FileNameIndexServiceImpl.java b/platform/lang-impl/src/com/intellij/psi/search/FileNameIndexServiceImpl.java
index 7e97ea4f7ee1..239831f3b8d2 100644
--- a/platform/lang-impl/src/com/intellij/psi/search/FileNameIndexServiceImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/search/FileNameIndexServiceImpl.java
@@ -46,7 +46,7 @@ public class FileNameIndexServiceImpl implements FileNameIndexService {
}
@Override
- public void processAllFileNames(@NotNull Processor processor, @NotNull GlobalSearchScope scope, IdFilter filter) {
+ public void processAllFileNames(@NotNull Processor super String> processor, @NotNull GlobalSearchScope scope, IdFilter filter) {
myIndex.processAllKeys(FilenameIndexImpl.NAME, processor, scope, filter);
}
diff --git a/platform/lang-impl/src/com/intellij/psi/util/proximity/PsiProximityComparator.java b/platform/lang-impl/src/com/intellij/psi/util/proximity/PsiProximityComparator.java
index 213452e4d9c8..6ceccecb0f18 100644
--- a/platform/lang-impl/src/com/intellij/psi/util/proximity/PsiProximityComparator.java
+++ b/platform/lang-impl/src/com/intellij/psi/util/proximity/PsiProximityComparator.java
@@ -16,7 +16,6 @@
package com.intellij.psi.util.proximity;
-import com.intellij.extapi.psi.MetadataPsiElementBase;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.util.Computable;
@@ -86,8 +85,6 @@ public class PsiProximityComparator implements Comparator
- * If the return value is -1, no string suffix should be kept => a malformed escape sequence has been encountered.
- * If the return value is less than -1, no actual handing of the incomplete escape sequence should be performed,
- * the string suffix length should be decoded with {@code #decodeUnhandledSuffixLength(the return value)} and the suffix
- * should be preserved until the next output chunk is available.
- */
- private static int findConsecutiveEscSequencesEndIndex(@NotNull String text, int firstEscSeqBeginInd) {
- int escSeqBeginInd = firstEscSeqBeginInd;
- int lastMatchedColorEscSeqEndInd = -1;
- int escSeqEndInd;
- while ((escSeqEndInd = findEscSeqEndIndex(text, escSeqBeginInd)) >= 0) {
- if (text.charAt(escSeqEndInd) != 'm') {
- // Handle non-color escape sequences separately
- // ColoredOutputTypeRegistry expects only color escape sequences and in a single consecutive text chunk
- return lastMatchedColorEscSeqEndInd > 0 ? lastMatchedColorEscSeqEndInd : escSeqEndInd;
- }
- escSeqBeginInd = escSeqEndInd + 1;
- lastMatchedColorEscSeqEndInd = escSeqEndInd;
- if (escSeqEndInd + 1 >= text.length()) {
- return encodeUnhandledSuffixLength(text, firstEscSeqBeginInd);
- }
- if (text.charAt(escSeqEndInd + 1) != CSI.charAt(0)) {
- break;
- }
- if (escSeqEndInd + 2 >= text.length()) {
- return encodeUnhandledSuffixLength(text, firstEscSeqBeginInd);
- }
- if (text.charAt(escSeqEndInd + 2) != CSI.charAt(1)) {
- break;
- }
- }
- if (escSeqEndInd < -1) {
- return encodeUnhandledSuffixLength(text, firstEscSeqBeginInd);
- }
- return lastMatchedColorEscSeqEndInd;
- }
-
- /**
- * @implSpec {@code The ESC [ is followed by any number (including none) of "parameter bytes" in the
- * range 0x30-0x3F (ASCII 0-9:;<=>?), then by any number of "intermediate bytes" in the range 0x20-0x2F (ASCII space and
- * !"#$%&'()*+,-./), then finally by a single "final byte" in the range 0x40-0x7E (ASCII @A-Z[\]^_`a-z{|}~).}
- * @implNote Also, there are different sequences, aside CSI
- */
- private static int findEscSeqEndIndex(@NotNull String text, int escSeqBeginInd) {
- int parameterEndInd = escSeqBeginInd + CSI.length();
- while (parameterEndInd < text.length()) {
- char ch = text.charAt(parameterEndInd);
- if (0x30 <= ch && ch <= 0x3F) {
- parameterEndInd++;
- }
- else {
- break;
- }
- }
- while (parameterEndInd < text.length()) {
- char ch = text.charAt(parameterEndInd);
- if (0x20 <= ch && ch <= 0x2F) {
- parameterEndInd++;
- }
- else {
- break;
- }
- }
- if (parameterEndInd == text.length()) {
- return encodeUnhandledSuffixLength(text, escSeqBeginInd);
- }
- char lastChar = text.charAt(parameterEndInd);
- return 0x40 <= lastChar && lastChar <= 0x7E ? parameterEndInd : -1;
- }
-
- private static int encodeUnhandledSuffixLength(@NotNull String text, int suffixStartInd) {
- return -1 - (text.length() - suffixStartInd);
- }
-
- private static int decodeUnhandledSuffixLength(int encodedUnhandledSuffixLength) {
- if (encodedUnhandledSuffixLength >= -1) {
- throw new AssertionError();
- }
- return -encodedUnhandledSuffixLength - 1;
}
@Nullable
@@ -252,10 +118,10 @@ public class AnsiEscapeDecoder {
@NotNull
protected Key getCurrentOutputAttributes(@NotNull Key outputType) {
if (ProcessOutputType.isStdout(outputType)) {
- return ObjectUtils.notNull(myCurrentStdoutOutputType, outputType);
+ return myStdoutEmulator.isInitialState() ? outputType : myColoredOutputTypeRegistry.getOutputType(myStdoutEmulator, outputType);
}
if (ProcessOutputType.isStderr(outputType)) {
- return ObjectUtils.notNull(myCurrentStderrOutputType, outputType);
+ return myStderrEmulator.isInitialState() ? outputType : myColoredOutputTypeRegistry.getOutputType(myStderrEmulator, outputType);
}
return outputType;
}
diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiStreamingLexer.java b/platform/platform-api/src/com/intellij/execution/process/AnsiStreamingLexer.java
new file mode 100644
index 000000000000..b78f435e6920
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/execution/process/AnsiStreamingLexer.java
@@ -0,0 +1,162 @@
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.execution.process;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+class AnsiStreamingLexer {
+ // element types
+ static final AnsiElementType TEXT = new AnsiElementType("TEXT");
+ static final AnsiElementType SGR = new AnsiElementType("SGR");
+ static final AnsiElementType CONTROL = new AnsiElementType("CONTROL");
+
+ static final char ESCAPE = '\u001b';
+ static final String CSI = ESCAPE + "[";
+ static final char SGR_SUFFIX = 'm';
+
+ // current text buffer
+ private String myBuffer = "";
+
+ // current token start offset
+ private int myStartOffset = 0;
+
+ // current token end offset
+ private int myEndOffset = 0;
+
+ private AnsiElementType myElementType = null;
+
+ /**
+ * Appending a {@code text} to the stream
+ */
+ void append(@NotNull String text) {
+ myBuffer = myEndOffset < myBuffer.length() ? myBuffer.substring(myEndOffset) + text : text;
+ myStartOffset = 0;
+ myEndOffset = 0;
+ }
+
+ /**
+ * @return element type of current token. null means we are not started or at the end of stream
+ */
+ @Nullable
+ AnsiElementType getElementType() {
+ return myElementType;
+ }
+
+ /**
+ * @return text of current token of null if we've not started or at the end of stream
+ */
+ @Nullable
+ String getElementText() {
+ return myElementType == null ? null : myBuffer.substring(myStartOffset, myEndOffset);
+ }
+
+ /**
+ * @return for {@link #SGR} elements return only content part of the text, between {@code CSI} and {@code m}. For the rest works
+ * the same way as {@link #getElementText()}
+ */
+ @Nullable
+ String getElementTextSmart() {
+ if (myElementType == SGR) {
+ return myBuffer.substring(myStartOffset + CSI.length(), myEndOffset - 1);
+ }
+ return getElementText();
+ }
+
+ /**
+ * advances lexer to the next token if possible
+ */
+ void advance() {
+ if (myEndOffset == myBuffer.length()) {
+ // EOF
+ myElementType = null;
+ return;
+ }
+ myStartOffset = myEndOffset;
+ if (myBuffer.charAt(myEndOffset) != ESCAPE) {
+ // just a text
+ advanceToEscape();
+ return;
+ }
+ if (myEndOffset + 1 == myBuffer.length()) {
+ incompleteSequence();
+ return;
+ }
+
+ myEndOffset++;
+ if (myBuffer.charAt(myEndOffset) == '[') {
+ myEndOffset++;
+ processCSISequence();
+ return;
+ }
+ // There can by anything from 0x40–0x5F https://en.wikipedia.org/wiki/ANSI_escape_code#Escape_sequences
+ // but we are ignoring this for now
+ advanceToEscape();
+ }
+
+ /**
+ * Advancing after CSI sequence, see https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences
+ *
+ * @implSpec {@code The ESC [ is followed by any number (including none) of "parameter bytes" in the
+ * range 0x30–0x3F (ASCII 0–9:;<=>?), then by any number of "intermediate bytes" in the range 0x20–0x2F (ASCII space and
+ * !"#$%&'()*+,-./), then finally by a single "final byte" in the range 0x40–0x7E (ASCII @A–Z[\]^_`a–z{|}~).}
+ */
+ private void processCSISequence() {
+ while (myEndOffset < myBuffer.length() && isInRange(myBuffer.charAt(myEndOffset), (char)0x30, (char)0x3F)) {
+ myEndOffset++;
+ }
+ while (myEndOffset < myBuffer.length() && isInRange(myBuffer.charAt(myEndOffset), (char)0x20, (char)0x2F)) {
+ myEndOffset++;
+ }
+ if (myEndOffset == myBuffer.length()) {
+ incompleteSequence();
+ return;
+ }
+
+ char lastChar = myBuffer.charAt(myEndOffset);
+ myEndOffset++;
+ if (lastChar == SGR_SUFFIX) {
+ myElementType = SGR;
+ }
+ else if (0x40 <= lastChar && lastChar <= 0x7E) {
+ myElementType = CONTROL;
+ }
+ else {
+ // broken seqeuence, considering as a text
+ advanceToEscape();
+ }
+ }
+
+ private void advanceToEscape() {
+ int escapeIndex = myBuffer.indexOf(ESCAPE, myEndOffset);
+ myEndOffset = escapeIndex != -1 ? escapeIndex : myBuffer.length();
+ myElementType = TEXT;
+ }
+
+ private void incompleteSequence() {
+ myElementType = null;
+ myEndOffset = myStartOffset;
+ }
+
+ /**
+ * @return true iff {@code character} is inside chars range inclusive
+ */
+ private static boolean isInRange(char character, char startRange, char endRange) {
+ return startRange <= character && character <= endRange;
+ }
+
+ /**
+ * representing element type for ANSI stream. Not using ElementType to avoid wasting tokens
+ */
+ static final class AnsiElementType {
+ private final String myName;
+
+ private AnsiElementType(String name) {
+ myName = name;
+ }
+
+ @Override
+ public String toString() {
+ return "ANSI: " + myName;
+ }
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalColor.java b/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalColor.java
new file mode 100644
index 000000000000..5ede1f42465f
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalColor.java
@@ -0,0 +1,31 @@
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.execution.process;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+
+/**
+ * Interface to work with ANSI-defined terminal colors
+ */
+interface AnsiTerminalColor {
+ /**
+ * @return command part for serializing this color.
+ * @implSpec this method MUST NOT return an escape sequence. Only the part that should be wrapped to {@link #SGR_COMMAND_FG_COLOR_ENCODED} or
+ * {@link #SGR_COMMAND_BG_COLOR_ENCODED}. E.g. {@code 2;255;255;255 }
+ */
+ @NotNull
+ String getAnsiEncodedColor();
+
+ /**
+ * @return a {@link java.awt.Color color} representing this one or null if this is a pre-set configurable color 0-15
+ */
+ @Nullable
+ Color getColor();
+
+ /**
+ * @return a color index for this terminal color if available. Returns {@code -1} for pure RGB encoded color
+ */
+ int getColorIndex();
+}
diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalEmulator.java b/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalEmulator.java
new file mode 100644
index 000000000000..fd1fc7c77b5c
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/execution/process/AnsiTerminalEmulator.java
@@ -0,0 +1,702 @@
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.execution.process;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.markup.EffectType;
+import com.intellij.openapi.util.ClearableLazyValue;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.IntConsumer;
+
+import static com.intellij.execution.process.AnsiCommands.*;
+import static com.intellij.execution.process.AnsiStreamingLexer.SGR_SUFFIX;
+import static com.intellij.execution.process.AnsiTerminalEmulator.BlinkSpeed.RAPID_BLINK;
+import static com.intellij.execution.process.AnsiTerminalEmulator.BlinkSpeed.SLOW_BLINK;
+import static com.intellij.execution.process.AnsiTerminalEmulator.Boldness.BOLD;
+import static com.intellij.execution.process.AnsiTerminalEmulator.Boldness.FAINT;
+import static com.intellij.execution.process.AnsiTerminalEmulator.FrameType.*;
+import static com.intellij.execution.process.AnsiTerminalEmulator.Underline.DOUBLE_UNDERLINE;
+import static com.intellij.execution.process.AnsiTerminalEmulator.Underline.SINGLE_UNDERLINE;
+import static com.intellij.openapi.editor.markup.EffectType.BOLD_LINE_UNDERSCORE;
+import static com.intellij.openapi.editor.markup.EffectType.LINE_UNDERSCORE;
+
+/**
+ * Emulates the ANSI terminal state
+ */
+class AnsiTerminalEmulator {
+ private static final Logger LOG = Logger.getInstance(AnsiTerminalEmulator.class);
+
+ private static final AnsiTerminalEmulator EMPTY_EMULATOR = new AnsiTerminalEmulator();
+ private static final int MAX_8BIT_COLOR_INDEX = 15;
+ private static final int COLOR_CUBE_MIN_INDEX = MAX_8BIT_COLOR_INDEX + 1;
+ private static final int GRAY_MIN_INDEX = 232;
+
+ @NotNull
+ private Font myFont = Font.DEFAULT;
+ @NotNull
+ private Boldness myBoldness = Boldness.DEFAULT;
+ @NotNull
+ private Underline myUnderline = Underline.DEFAULT;
+ @NotNull
+ private BlinkSpeed myBlink = BlinkSpeed.DEFAULT;
+ @NotNull
+ private FrameType myFrameType = FrameType.DEFAULT;
+
+ private boolean myIsItalic;
+ private boolean myIsInverse;
+ private boolean myIsConseal;
+ private boolean myIsCrossedOut;
+ private boolean myIsFraktur;
+ private boolean myIsOverlined;
+
+ private AnsiTerminalColor myBackgroundColor;
+ private AnsiTerminalColor myForegroundColor;
+
+ private final ClearableLazyValue mySerializedSgrStateProvider = ClearableLazyValue.create(
+ () -> computeAnsiSerializedSGRState());
+
+ /**
+ * Consumes SGR - Select Graphic Rendition control sequence and changes emulator's state accordingly
+ */
+ public void processSgr(@NotNull String sgrSequenceBody) {
+ /*
+ The ITU's T.416 Information technology - Open Document Architecture (ODA) and interchange format:
+ https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.416-199303-I!!PDF-E&type=items
+ uses ':' as separator characters instead *
+ */
+ List sgrSequenceParts = StringUtil.split(sgrSequenceBody, StringUtil.containsChar(sgrSequenceBody, ':') ? ":" : ";");
+ Iterator sgrCodesIterator = ContainerUtil.map(sgrSequenceParts, it -> {
+ try {
+ return it.isEmpty() ? 0 : Integer.parseInt(it);
+ }
+ catch (NumberFormatException e) {
+ LOG.warn("Could not parse integer: " + it + " in " + sgrSequenceBody);
+ return null;
+ }
+ }).iterator();
+
+ while (sgrCodesIterator.hasNext()) {
+ Integer command = sgrCodesIterator.next();
+ if (command == null) {
+ break;
+ }
+ processSgr(command, sgrCodesIterator);
+ }
+ }
+
+ /**
+ * Changes terminal state according to {@code commandCode}
+ * @param sgrCodesIterator iterator of subsequent codes if any. May be necessary for multi-param sgr sequences, like setting color
+ */
+ private void processSgr(int commandCode, Iterator sgrCodesIterator) {
+ switch (commandCode) {
+ case SGR_COMMAND_RESET:
+ resetTerminal();
+ break;
+ case SGR_COMMAND_BOLD:
+ myBoldness = BOLD;
+ break;
+ case SGR_COMMAND_FAINT:
+ myBoldness = FAINT;
+ break;
+ case SGR_COMMAND_ITALIC:
+ myIsItalic = true;
+ break;
+ case SGR_COMMAND_UNDERLINE:
+ myUnderline = SINGLE_UNDERLINE;
+ break;
+ case SGR_COMMAND_BLINK_SLOW:
+ myBlink = SLOW_BLINK;
+ break;
+ case SGR_COMMAND_BLINK_RAPID:
+ myBlink = RAPID_BLINK;
+ break;
+ case SGR_COMMAND_INVERSE:
+ myIsInverse = true;
+ break;
+ case SGR_COMMAND_CONCEAL:
+ myIsConseal = true;
+ break;
+ case SGR_COMMAND_CROSS_OUT:
+ myIsCrossedOut = true;
+ break;
+ case SGR_COMMAND_PRIMARY_FONT:
+ myFont = Font.DEFAULT;
+ break;
+ case SGR_COMMAND_FRAKTUR:
+ myIsFraktur = true;
+ break;
+ case SGR_COMMAND_DOUBLE_UNDERLINE:
+ myBoldness = Boldness.DEFAULT;
+ // this is ECMA-48 behaviour. Probably we could make this configurable via flag?
+ myUnderline = DOUBLE_UNDERLINE;
+ break;
+ case SGR_COMMAND_NO_BOLD_FAINT:
+ myBoldness = Boldness.DEFAULT;
+ break;
+ case SGR_COMMAND_NO_ITALIC_FRAKTUR:
+ myIsFraktur = false;
+ myIsItalic = false;
+ break;
+ case SGR_COMMAND_NO_UNDERLINE:
+ myUnderline = Underline.DEFAULT;
+ break;
+ case SGR_COMMAND_NO_BLINK:
+ myBlink = BlinkSpeed.DEFAULT;
+ break;
+ case SGR_COMMAND_NO_INVERSE:
+ myIsInverse = false;
+ break;
+ case SGR_COMMAND_REVEAL:
+ myIsConseal = false;
+ break;
+ case SGR_COMMAND_NO_CROSS_OUT:
+ myIsCrossedOut = false;
+ break;
+ case SGR_COMMAND_FG_COLOR_ENCODED:
+ myForegroundColor = decodeColor(sgrCodesIterator);
+ break;
+ case SGR_COMMAND_FG_COLOR_DEFAULT:
+ myForegroundColor = null;
+ break;
+ case SGR_COMMAND_BG_COLOR_ENCODED:
+ myBackgroundColor = decodeColor(sgrCodesIterator);
+ break;
+ case SGR_COMMAND_BG_COLOR_DEFAULT:
+ myBackgroundColor = null;
+ break;
+ case SGR_COMMAND_FRAMED:
+ myFrameType = FRAMED;
+ break;
+ case SGR_COMMAND_ENCIRCLED:
+ myFrameType = ENCIRCLED;
+ break;
+ case SGR_COMMAND_OVERLINED:
+ myIsOverlined = true;
+ break;
+ case SGR_COMMAND_NO_FRAMED_ENCIRCLED:
+ myFrameType = NO_FRAME;
+ break;
+ case SGR_COMMAND_NO_OVERLINED:
+ myIsOverlined = false;
+ break;
+ default:
+ if (commandCode >= SGR_COMMAND_FONT1 && commandCode <= SGR_COMMAND_FONT9) {
+ myFont = Font.values()[commandCode - 10];
+ }
+ else if (commandCode >= SGR_COMMAND_FG_COLOR0 && commandCode <= SGR_COMMAND_FG_COLOR7) {
+ myForegroundColor = new EightBitColor(commandCode - SGR_COMMAND_FG_COLOR0);
+ }
+ else if (commandCode >= SGR_COMMAND_BG_COLOR0 && commandCode <= SGR_COMMAND_BG_COLOR7) {
+ myBackgroundColor = new EightBitColor(commandCode - SGR_COMMAND_BG_COLOR0);
+ }
+ else if (commandCode >= SGR_COMMAND_IDEOGRAM_UNDER_RIGHT && commandCode <= SGR_COMMAND_IDEOGRAM_OFF) {
+ LOG.debug("Ignore no-op ideogram sequence: " + commandCode);
+ }
+ else if (commandCode >= SGR_COMMAND_FG_COLOR8 && commandCode <= SGR_COMMAND_FG_COLOR15) {
+ myForegroundColor = new EightBitColor(commandCode - SGR_COMMAND_FG_COLOR8 + 8);
+ }
+ else if (commandCode >= SGR_COMMAND_BG_COLOR8 && commandCode <= SGR_COMMAND_BG_COLOR15) {
+ myBackgroundColor = new EightBitColor(commandCode - SGR_COMMAND_BG_COLOR8 + 8);
+ }
+ else {
+ LOG.warn("Unknown command " + commandCode);
+ return;
+ }
+ }
+ mySerializedSgrStateProvider.drop();
+ }
+
+ /**
+ * @return an ANSI string representing the SGR state of the current emulator. Same state is always represented with the same string.
+ */
+ @NotNull
+ public String getAnsiSerializedSGRState() {
+ return Objects.requireNonNull(mySerializedSgrStateProvider.getValue());
+ }
+
+ /**
+ * @return an ANSI string representing the SGR state of the current emulator. Same state is always represented with the same string.
+ */
+ @NotNull
+ public String computeAnsiSerializedSGRState() {
+ List state = new ArrayList<>();
+ IntConsumer codeConsumer = it -> state.add(Integer.toString(it));
+
+ codeConsumer.accept(SGR_COMMAND_RESET);
+ if (myFont != Font.DEFAULT) {
+ codeConsumer.accept(myFont.sgrCode);
+ }
+ if (myBoldness != Boldness.DEFAULT) {
+ codeConsumer.accept(myBoldness.sgrCode);
+ }
+ if (myUnderline != Underline.DEFAULT) {
+ codeConsumer.accept(myUnderline.sgrCode);
+ }
+ if (myFont != Font.DEFAULT) {
+ codeConsumer.accept(myFont.sgrCode);
+ }
+ if (myBlink != BlinkSpeed.DEFAULT) {
+ codeConsumer.accept(myBlink.sgrCode);
+ }
+ if (myIsInverse) {
+ codeConsumer.accept(SGR_COMMAND_INVERSE);
+ }
+ if (myBackgroundColor != null) {
+ codeConsumer.accept(SGR_COMMAND_BG_COLOR_ENCODED);
+ state.add(myBackgroundColor.getAnsiEncodedColor());
+ }
+ if (myForegroundColor != null) {
+ codeConsumer.accept(SGR_COMMAND_FG_COLOR_ENCODED);
+ state.add(myForegroundColor.getAnsiEncodedColor());
+ }
+ if (myIsItalic) {
+ codeConsumer.accept(SGR_COMMAND_ITALIC);
+ }
+ if (myIsConseal) {
+ codeConsumer.accept(SGR_COMMAND_CONCEAL);
+ }
+ if (myIsCrossedOut) {
+ codeConsumer.accept(SGR_COMMAND_CROSS_OUT);
+ }
+ if (myIsFraktur) {
+ codeConsumer.accept(SGR_COMMAND_FRAKTUR);
+ }
+ if (myFrameType != FrameType.DEFAULT) {
+ codeConsumer.accept(myFrameType.sgrCode);
+ }
+ if (myIsOverlined) {
+ codeConsumer.accept(SGR_COMMAND_OVERLINED);
+ }
+ return AnsiStreamingLexer.CSI + StringUtil.join(state, ";") + SGR_SUFFIX;
+ }
+
+ /**
+ * Reset terminal values to defaults
+ */
+ private void resetTerminal() {
+ myFont = EMPTY_EMULATOR.myFont;
+ myBoldness = EMPTY_EMULATOR.myBoldness;
+ myUnderline = EMPTY_EMULATOR.myUnderline;
+ myBackgroundColor = EMPTY_EMULATOR.myBackgroundColor;
+ myForegroundColor = EMPTY_EMULATOR.myForegroundColor;
+ myFrameType = EMPTY_EMULATOR.myFrameType;
+ myBlink = EMPTY_EMULATOR.myBlink;
+ myIsInverse = EMPTY_EMULATOR.myIsInverse;
+ myIsItalic = EMPTY_EMULATOR.myIsItalic;
+ myIsConseal = EMPTY_EMULATOR.myIsConseal;
+ myIsCrossedOut = EMPTY_EMULATOR.myIsCrossedOut;
+ myIsFraktur = EMPTY_EMULATOR.myIsFraktur;
+ myIsOverlined = EMPTY_EMULATOR.myIsOverlined;
+ mySerializedSgrStateProvider.drop();
+ }
+
+ /**
+ * @return true if emulator is in it's initial state
+ * @see #resetTerminal()
+ */
+ public boolean isInitialState() {
+ return EMPTY_EMULATOR.equals(this);
+ }
+
+ @Nullable
+ public Color getBackgroundColor() {
+ return myBackgroundColor == null ? null : myBackgroundColor.getColor();
+ }
+
+ public int getBackgroundColorIndex() {
+ return myBackgroundColor == null ? -1 : myBackgroundColor.getColorIndex();
+ }
+
+ @Nullable
+ public Color getForegroundColor() {
+ return myForegroundColor == null ? null : myForegroundColor.getColor();
+ }
+
+ public int getForegroundColorIndex() {
+ return myForegroundColor == null ? -1 : myForegroundColor.getColorIndex();
+ }
+
+ public boolean isInverse() {
+ return myIsInverse;
+ }
+
+ @NotNull
+ public Underline getUnderline() {
+ return myUnderline;
+ }
+
+ @NotNull
+ public FrameType getFrameType() {
+ return myFrameType;
+ }
+
+ public boolean isCrossedOut() {
+ return myIsCrossedOut;
+ }
+
+ @NotNull
+ public Boldness getBoldness() {
+ return myBoldness;
+ }
+
+ public boolean isItalic() {
+ return myIsItalic;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AnsiTerminalEmulator emulator = (AnsiTerminalEmulator)o;
+
+ if (myIsItalic != emulator.myIsItalic) return false;
+ if (myIsInverse != emulator.myIsInverse) return false;
+ if (myIsConseal != emulator.myIsConseal) return false;
+ if (myIsCrossedOut != emulator.myIsCrossedOut) return false;
+ if (myIsFraktur != emulator.myIsFraktur) return false;
+ if (myIsOverlined != emulator.myIsOverlined) return false;
+ if (myFont != emulator.myFont) return false;
+ if (myBoldness != emulator.myBoldness) return false;
+ if (myUnderline != emulator.myUnderline) return false;
+ if (myBlink != emulator.myBlink) return false;
+ if (myFrameType != emulator.myFrameType) return false;
+ if (!Objects.equals(myBackgroundColor, emulator.myBackgroundColor)) {
+ return false;
+ }
+ if (!Objects.equals(myForegroundColor, emulator.myForegroundColor)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myFont.hashCode();
+ result = 31 * result + myBoldness.hashCode();
+ result = 31 * result + myUnderline.hashCode();
+ result = 31 * result + myBlink.hashCode();
+ result = 31 * result + myFrameType.hashCode();
+ result = 31 * result + (myIsItalic ? 1 : 0);
+ result = 31 * result + (myIsInverse ? 1 : 0);
+ result = 31 * result + (myIsConseal ? 1 : 0);
+ result = 31 * result + (myIsCrossedOut ? 1 : 0);
+ result = 31 * result + (myIsFraktur ? 1 : 0);
+ result = 31 * result + (myIsOverlined ? 1 : 0);
+ result = 31 * result + (myBackgroundColor != null ? myBackgroundColor.hashCode() : 0);
+ result = 31 * result + (myForegroundColor != null ? myForegroundColor.hashCode() : 0);
+ return result;
+ }
+
+ /**
+ * Decodes ANSI SGR sequences 38 && 48. Encodings may be:
+ *
+ * - 5;n - with index-based encoding
+ * - 2;r;g;b - with red, green and blue parts
+ *
+ */
+ private static AnsiTerminalColor decodeColor(@NotNull Iterator encodedColorIterator) {
+ if (!encodedColorIterator.hasNext()) {
+ return null;
+ }
+ int encodingType = encodedColorIterator.next();
+ if (encodingType == SGR_COLOR_ENCODING_RGB) {
+ Integer redCode = encodedColorIterator.hasNext() ? encodedColorIterator.next() : null;
+ Integer greenCode = encodedColorIterator.hasNext() ? encodedColorIterator.next() : null;
+ Integer blueCode = encodedColorIterator.hasNext() ? encodedColorIterator.next() : null;
+ if (redCode != null && greenCode != null && blueCode != null) {
+ return new RGBColor(redCode, greenCode, blueCode);
+ }
+ }
+ else if (encodingType == SGR_COLOR_ENCODING_INDEXED) {
+ Integer encodedColor = encodedColorIterator.hasNext() ? encodedColorIterator.next() : null;
+ if (encodedColor != null) {
+ return decode8BitColor(encodedColor);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Decodes index-encoded color from SGR
+ *
+ * @see 5;n - with index-based encoding
+ */
+ private static AnsiTerminalColor decode8BitColor(int encodedColor) {
+ if (encodedColor >= 0 && encodedColor <= MAX_8BIT_COLOR_INDEX) {
+ return new EightBitColor(encodedColor);
+ }
+ else if (encodedColor >= COLOR_CUBE_MIN_INDEX && encodedColor <= 255) {
+ //16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+ //232-255: grayscale from black to white in 24 steps
+ return new EightBitRGBColor(encodedColor);
+ }
+ return null;
+ }
+
+ public enum FrameType {
+ NO_FRAME(SGR_COMMAND_NO_FRAMED_ENCIRCLED, null),
+ FRAMED(SGR_COMMAND_FRAMED, EffectType.BOXED),
+ ENCIRCLED(SGR_COMMAND_ENCIRCLED, EffectType.ROUNDED_BOX);
+
+ private static final FrameType DEFAULT = NO_FRAME;
+ /**
+ * SGR sequence code that should be used to switch to this option
+ */
+ public final int sgrCode;
+
+ @Nullable
+ public final EffectType effectType;
+
+ FrameType(int sgrCode, @Nullable EffectType effectType) {
+ this.sgrCode = sgrCode;
+ this.effectType = effectType;
+ }
+ }
+
+ public enum BlinkSpeed {
+ NO_BLINK(SGR_COMMAND_NO_BLINK),
+ SLOW_BLINK(SGR_COMMAND_BLINK_SLOW),
+ RAPID_BLINK(SGR_COMMAND_BLINK_RAPID);
+
+ private static final BlinkSpeed DEFAULT = NO_BLINK;
+ /**
+ * SGR sequence code that should be used to switch to this option
+ */
+ public final int sgrCode;
+
+ BlinkSpeed(int sgrCode) {
+ this.sgrCode = sgrCode;
+ }
+ }
+
+ public enum Boldness {
+ FAINT(SGR_COMMAND_FAINT),
+ NORMAL(SGR_COMMAND_NO_BOLD_FAINT),
+ BOLD(SGR_COMMAND_BOLD);
+
+ private static final Boldness DEFAULT = NORMAL;
+ /**
+ * SGR sequence code that should be used to switch to this option
+ */
+ public final int sgrCode;
+
+ Boldness(int sgrCode) {
+ this.sgrCode = sgrCode;
+ }
+ }
+
+ public enum Underline {
+ NO_UNDERLINE(SGR_COMMAND_NO_UNDERLINE, null),
+ SINGLE_UNDERLINE(SGR_COMMAND_UNDERLINE, LINE_UNDERSCORE),
+ DOUBLE_UNDERLINE(SGR_COMMAND_DOUBLE_UNDERLINE, BOLD_LINE_UNDERSCORE);
+
+ private static final Underline DEFAULT = NO_UNDERLINE;
+ /**
+ * SGR sequence code that should be used to switch to this option
+ */
+ public final int sgrCode;
+
+ @Nullable
+ public final EffectType effectType;
+
+ Underline(int sgrCode, @Nullable EffectType effectType) {
+ this.sgrCode = sgrCode;
+ this.effectType = effectType;
+ }
+ }
+
+ public enum Font {
+ DEFAULT(SGR_COMMAND_PRIMARY_FONT),
+ ALT1(SGR_COMMAND_FONT1),
+ ALT2(SGR_COMMAND_FONT2),
+ ALT3(SGR_COMMAND_FONT3),
+ ALT4(SGR_COMMAND_FONT4),
+ ALT5(SGR_COMMAND_FONT5),
+ ALT6(SGR_COMMAND_FONT6),
+ ALT7(SGR_COMMAND_FONT7),
+ ALT8(SGR_COMMAND_FONT8),
+ ALT9(SGR_COMMAND_FONT9);
+ /**
+ * SGR sequence code that should be used to switch to this option
+ */
+ public final int sgrCode;
+
+ Font(int sgrCode) {
+ this.sgrCode = sgrCode;
+ }
+ }
+
+ /**
+ * Represents a 24 bit color, encoded with {@link AnsiCommands#SGR_COLOR_ENCODING_RGB}
+ */
+ private static final class RGBColor implements AnsiTerminalColor {
+ private final int myRed;
+ private final int myGreen;
+ private final int myBlue;
+
+ private RGBColor(int red, int green, int blue) {
+ myRed = red;
+ myGreen = green;
+ myBlue = blue;
+ }
+
+ @NotNull
+ @Override
+ public String getAnsiEncodedColor() {
+ return SGR_COLOR_ENCODING_RGB + ";" + myRed + ";" + myGreen + ";" + myBlue;
+ }
+
+
+ @Override
+ public int getColorIndex() {
+ return -1;
+ }
+
+ @NotNull
+ @Override
+ public Color getColor() {
+ //noinspection UseJBColor
+ return new Color(myRed, myGreen, myBlue);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ RGBColor color = (RGBColor)o;
+
+ if (myRed != color.myRed) return false;
+ if (myGreen != color.myGreen) return false;
+ if (myBlue != color.myBlue) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myRed;
+ result = 31 * result + myGreen;
+ result = 31 * result + myBlue;
+ return result;
+ }
+ }
+
+ /**
+ * Base class for index-based colors - 8bit and 8bit rgb colors
+ */
+ private abstract static class IndexedAnsiTerminalColor implements AnsiTerminalColor {
+ private final int myColorIndex;
+
+ protected IndexedAnsiTerminalColor(int colorIndex) {
+ myColorIndex = colorIndex;
+ }
+
+ @Override
+ public int getColorIndex() {
+ return myColorIndex;
+ }
+
+ @NotNull
+ @Override
+ public String getAnsiEncodedColor() {
+ return SGR_COLOR_ENCODING_INDEXED + ";" + getColorIndex();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ IndexedAnsiTerminalColor color = (IndexedAnsiTerminalColor)o;
+
+ if (myColorIndex != color.myColorIndex) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return myColorIndex;
+ }
+ }
+
+ /**
+ * Represents a simple indexed color for SGR commands:
+ *
+ * - {@link AnsiCommands#SGR_COMMAND_FG_COLOR0} - {@link AnsiCommands#SGR_COMMAND_FG_COLOR7}
+ * - {@link AnsiCommands#SGR_COMMAND_BG_COLOR0} - {@link AnsiCommands#SGR_COMMAND_BG_COLOR7}
+ * - {@link AnsiCommands#SGR_COMMAND_FG_COLOR8} - {@link AnsiCommands#SGR_COMMAND_FG_COLOR15}
+ * - {@link AnsiCommands#SGR_COMMAND_BG_COLOR8} - {@link AnsiCommands#SGR_COMMAND_BG_COLOR15}
+ *
+ * Also used for first 15 indexed colors from {@link AnsiCommands#SGR_COMMAND_FG_COLOR_ENCODED} and {@link AnsiCommands#SGR_COMMAND_BG_COLOR_ENCODED}
+ */
+ private static class EightBitColor extends IndexedAnsiTerminalColor {
+
+ private EightBitColor(int colorIndex) {
+ super(colorIndex);
+ if (colorIndex < 0 || colorIndex > MAX_8BIT_COLOR_INDEX) {
+ LOG.error("Wrong 8bit color index: " + colorIndex);
+ }
+ }
+
+ @Nullable
+ @Override
+ public Color getColor() {
+ return null;
+ }
+ }
+
+ /**
+ * Represents rgb colors encoded with {@link AnsiCommands#SGR_COLOR_ENCODING_INDEXED} from 16-231 and 232-255
+ */
+ private static final class EightBitRGBColor extends IndexedAnsiTerminalColor {
+
+ // 8-bit color encoding for range 16-231
+ private static final int[] CUBE_STEPS = {
+ 0x0, 0x5f, 0x87, 0xaf, 0xd7, 0xff
+ };
+ // 8-bit grayscale encoding for range 232-255
+ private static final int[] GRAYSCALE_STEPS = {
+ 0x08, 0x12, 0x1c, 0x26, 0x30, 0x3a, 0x44, 0x4e,
+ 0x58, 0x62, 0x6c, 0x76, 0x80, 0x8a, 0x94, 0x9e,
+ 0xa8, 0xb2, 0xbc, 0xc6, 0xd0, 0xda, 0xe4, 0xee
+ };
+
+ private EightBitRGBColor(int colorIndex) {
+ super(colorIndex);
+ if (colorIndex < COLOR_CUBE_MIN_INDEX || colorIndex > 255) {
+ LOG.error("Wrong indexed RGB color index: " + colorIndex);
+ }
+ }
+
+ @Nullable
+ @Override
+ public Color getColor() {
+ int colorIndex = getColorIndex();
+ if (colorIndex >= COLOR_CUBE_MIN_INDEX && colorIndex < GRAY_MIN_INDEX) {
+ int encodedColor = colorIndex - COLOR_CUBE_MIN_INDEX;
+ //noinspection UseJBColor
+ return new Color(CUBE_STEPS[(encodedColor / 36) % 6], CUBE_STEPS[(encodedColor / 6) % 6], CUBE_STEPS[encodedColor % 6]);
+ }
+ else if (colorIndex >= GRAY_MIN_INDEX && colorIndex <= 255) {
+ int colorPart = GRAYSCALE_STEPS[colorIndex - GRAY_MIN_INDEX];
+ //noinspection UseJBColor
+ return new Color(colorPart, colorPart, colorPart);
+ }
+ return null;
+ }
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java
index 68e39cc501ca..7669e9af0500 100644
--- a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java
+++ b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java
@@ -30,6 +30,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
/**
@@ -113,12 +116,33 @@ public class ColoredOutputTypeRegistry {
return streamOutputType;
}
ProcessOutputType newKey = new ProcessOutputType(completeAttribute, streamOutputType);
- AnsiConsoleViewContentType contentType = createAnsiConsoleViewContentType(attribute);
- ConsoleViewContentType.registerNewConsoleViewType(newKey, contentType);
+ ConsoleViewContentType.registerNewConsoleViewType(newKey, createAnsiConsoleViewContentType(attribute));
attrsToKeyMap.put(completeAttribute, newKey);
return newKey;
}
+ /**
+ * Creates an {@link ProcessOutputType} from the {@link AnsiTerminalEmulator terminal emulator state} and stream type. Output type may be used
+ * later to print to the console
+ */
+ @NotNull
+ public ProcessOutputType getOutputType(@NotNull AnsiTerminalEmulator terminal, @NotNull Key streamType) {
+ Map attrsToKeyMap = ProcessOutputType.isStdout(streamType) ? myStdoutAttrsToKeyMap : myStderrAttrsToKeyMap;
+ String ansiSerializedState = terminal.getAnsiSerializedSGRState();
+ ProcessOutputType key = attrsToKeyMap.get(ansiSerializedState);
+ if (key != null) {
+ return key;
+ }
+
+ ProcessOutputType streamOutputType = streamType instanceof ProcessOutputType ?
+ (ProcessOutputType)streamType : (ProcessOutputType)ProcessOutputTypes.STDOUT;
+
+ ProcessOutputType newKey = new ProcessOutputType(ansiSerializedState, streamOutputType);
+ ConsoleViewContentType.registerNewConsoleViewType(newKey, new AnsiConsoleViewContentType(terminal));
+ attrsToKeyMap.put(ansiSerializedState, newKey);
+ return newKey;
+ }
+
/**
* @deprecated use {@link #getOutputType(String, Key)} instead
*/
@@ -165,7 +189,7 @@ public class ColoredOutputTypeRegistry {
}
@NotNull
- private static AnsiConsoleViewContentType createAnsiConsoleViewContentType(@NotNull String attribute) {
+ private static ConsoleViewContentType createAnsiConsoleViewContentType(@NotNull String attribute) {
int foregroundColor = -1;
int backgroundColor = -1;
boolean inverse = false;
@@ -224,30 +248,100 @@ public class ColoredOutputTypeRegistry {
}
private static class AnsiConsoleViewContentType extends ConsoleViewContentType {
- private final int myBackgroundColor;
- private final int myForegroundColor;
+ private final int myBackgroundColorIndex;
+ private final int myForegroundColorIndex;
+ @Nullable
+ private final Color myEnforcedBackgroundColor;
+ @Nullable
+ private final Color myEnforcedForegroundColor;
private final boolean myInverse;
- private final EffectType myEffectType;
+ @NotNull
+ private final List myEffectTypes;
private final int myFontType;
+ private AnsiConsoleViewContentType(@NotNull String attribute,
+ int backgroundColorIndex,
+ int foregroundColorIndex,
+ @Nullable Color enforcedBackgroundColor,
+ @Nullable Color enforcedForegroundColor,
+ boolean inverse,
+ @NotNull List effectTypes,
+ int fontType) {
+ super(attribute, ConsoleViewContentType.NORMAL_OUTPUT_KEY);
+ myBackgroundColorIndex = backgroundColorIndex;
+ myEnforcedBackgroundColor = enforcedBackgroundColor;
+ myForegroundColorIndex = foregroundColorIndex;
+ myEnforcedForegroundColor = enforcedForegroundColor;
+ myInverse = inverse;
+ myEffectTypes = effectTypes.isEmpty() ? ContainerUtil.emptyList() : ContainerUtil.immutableList(effectTypes);
+ myFontType = fontType;
+ }
+
private AnsiConsoleViewContentType(@NotNull String attribute,
int backgroundColor,
int foregroundColor,
boolean inverse,
@Nullable EffectType effectType,
int fontType) {
- super(attribute, ConsoleViewContentType.NORMAL_OUTPUT_KEY);
- myBackgroundColor = backgroundColor;
- myForegroundColor = foregroundColor;
- myInverse = inverse;
- myEffectType = effectType;
- myFontType = fontType;
+ this(attribute, backgroundColor, foregroundColor, null, null, inverse,
+ effectType == null ? Collections.emptyList() : Collections.singletonList(effectType), fontType);
+ }
+
+ private AnsiConsoleViewContentType(@NotNull AnsiTerminalEmulator terminalEmulator) {
+ this(terminalEmulator.getAnsiSerializedSGRState(),
+ terminalEmulator.getBackgroundColorIndex(),
+ terminalEmulator.getForegroundColorIndex(),
+ terminalEmulator.getBackgroundColor(),
+ terminalEmulator.getForegroundColor(),
+ terminalEmulator.isInverse(),
+ computeEffectTypes(terminalEmulator),
+ computeAwtFont(terminalEmulator));
+ }
+
+ /**
+ * Computes effect types that can be represented by our editor
+ */
+ @NotNull
+ private static List computeEffectTypes(@NotNull AnsiTerminalEmulator terminalEmulator) {
+ ArrayList result = ContainerUtil.newArrayList();
+ AnsiTerminalEmulator.Underline underline = terminalEmulator.getUnderline();
+ if (underline == AnsiTerminalEmulator.Underline.SINGLE_UNDERLINE) {
+ result.add(EffectType.LINE_UNDERSCORE);
+ }
+ else if (underline == AnsiTerminalEmulator.Underline.DOUBLE_UNDERLINE) {
+ result.add(EffectType.BOLD_LINE_UNDERSCORE);
+ }
+ if (terminalEmulator.isCrossedOut()) {
+ result.add(EffectType.STRIKEOUT);
+ }
+ AnsiTerminalEmulator.FrameType frameType = terminalEmulator.getFrameType();
+ if (frameType == AnsiTerminalEmulator.FrameType.FRAMED) {
+ result.add(EffectType.BOXED);
+ }
+ else if (frameType == AnsiTerminalEmulator.FrameType.ENCIRCLED) {
+ result.add(EffectType.ROUNDED_BOX);
+ }
+ return result;
+ }
+
+ /**
+ * Computes font style from boldness/italic flags
+ */
+ private static int computeAwtFont(@NotNull AnsiTerminalEmulator terminalEmulator) {
+ int result = 0;
+ if (terminalEmulator.getBoldness() == AnsiTerminalEmulator.Boldness.BOLD) {
+ result = Font.BOLD;
+ }
+ if (terminalEmulator.isItalic()) {
+ result |= Font.ITALIC;
+ }
+ return result;
}
@Override
public TextAttributes getAttributes() {
TextAttributes attrs = new TextAttributes();
- attrs.setEffectType(myEffectType);
+ attrs.setEffectType(null); // re-setting default BOX
if (myFontType != -1) {
attrs.setFontType(myFontType);
}
@@ -257,21 +351,25 @@ public class ColoredOutputTypeRegistry {
attrs.setForegroundColor(backgroundColor);
attrs.setEffectColor(backgroundColor);
attrs.setBackgroundColor(foregroundColor);
+ myEffectTypes.forEach(it -> attrs.withAdditionalEffect(it, backgroundColor));
}
else {
attrs.setForegroundColor(foregroundColor);
attrs.setEffectColor(foregroundColor);
attrs.setBackgroundColor(backgroundColor);
+ myEffectTypes.forEach(it -> attrs.withAdditionalEffect(it, foregroundColor));
}
return attrs;
}
private Color getForegroundColor() {
- return myForegroundColor != -1 ? getAnsiColor(myForegroundColor) : getDefaultForegroundColor();
+ return myEnforcedForegroundColor != null ? myEnforcedForegroundColor :
+ myForegroundColorIndex != -1 ? getAnsiColor(myForegroundColorIndex) : getDefaultForegroundColor();
}
private Color getBackgroundColor() {
- return myBackgroundColor != -1 ? getAnsiColor(myBackgroundColor) : getDefaultBackgroundColor();
+ return myEnforcedBackgroundColor != null ? myEnforcedBackgroundColor :
+ myBackgroundColorIndex != -1 ? getAnsiColor(myBackgroundColorIndex) : getDefaultBackgroundColor();
}
}
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java
index 9d0b065093d6..cca1f4753de9 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java
@@ -676,10 +676,15 @@ public abstract class DialogWrapper {
return myCheckBoxDoNotShowDialog != null && myCheckBoxDoNotShowDialog.isVisible() ? myCheckBoxDoNotShowDialog : null;
}
- private final JBValue BASE_BUTTON_GAP = new JBValue.Float(UIUtil.isUnderWin10LookAndFeel() ? 8 : 12);
+ private static final JBValue BASE_BUTTON_GAP = new JBValue.Float(UIUtil.isUnderWin10LookAndFeel() ? 8 : 12);
@NotNull
protected JPanel createButtonsPanel(@NotNull List extends JButton> buttons) {
+ return layoutButtonsPanel(buttons);
+ }
+
+ @NotNull
+ public static JPanel layoutButtonsPanel(@NotNull List extends JButton> buttons) {
JPanel buttonsPanel = new NonOpaquePanel();
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
@@ -727,6 +732,26 @@ public abstract class DialogWrapper {
* @see DialogWrapper#DEFAULT_ACTION
*/
protected JButton createJButtonForAction(Action action) {
+ JButton button = createJButtonForAction(action, getRootPane());
+
+ int mnemonic = button.getMnemonic();
+ final Object name = action.getValue(Action.NAME);
+ if (mnemonic == KeyEvent.VK_Y && "Yes".equals(name)) {
+ myYesAction = action;
+ }
+ else if (mnemonic == KeyEvent.VK_N && "No".equals(name)) {
+ myNoAction = action;
+ }
+
+ if (action.getValue(FOCUSED_ACTION) != null) {
+ myPreferredFocusedComponent = button;
+ }
+
+ return button;
+ }
+
+ @NotNull
+ public static JButton createJButtonForAction(@NotNull Action action, @Nullable JRootPane rootPane) {
JButton button;
if (action instanceof OptionAction && UISettings.getShadowInstance().getAllowMergeButtons()) {
button = createJOptionsButton((OptionAction)action);
@@ -749,24 +774,12 @@ public abstract class DialogWrapper {
}
button.setMnemonic(mnemonic);
- final Object name = action.getValue(Action.NAME);
- if (mnemonic == KeyEvent.VK_Y && "Yes".equals(name)) {
- myYesAction = action;
- }
- else if (mnemonic == KeyEvent.VK_N && "No".equals(name)) {
- myNoAction = action;
- }
-
if (action.getValue(DEFAULT_ACTION) != null) {
- if (!myPeer.isHeadless()) {
- getRootPane().setDefaultButton(button);
+ if (rootPane != null) {
+ rootPane.setDefaultButton(button);
}
}
- if (action.getValue(FOCUSED_ACTION) != null) {
- myPreferredFocusedComponent = button;
- }
-
return button;
}
diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java
index 51d5f0fbd057..735b7ba238c9 100644
--- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java
+++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java
@@ -109,6 +109,13 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co
return new MyIterator();
}
+ @NotNull
+ public ColoredIterator iterator(int fromIndex) {
+ MyIterator iterator = new MyIterator();
+ iterator.myIndex = fromIndex - 1;
+ return iterator;
+ }
+
@SuppressWarnings("unused")
public boolean isIconOnTheRight() {
return myIconOnTheRight;
@@ -859,7 +866,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co
else if (attributes.isClickable()) {
fgColor = ObjectUtils.notNull(attributes.getFgColor(), UIUtil.getLabelForeground());
Color bg = ObjectUtils.notNull(attributes.getBgColor(), UIUtil.getLabelBackground());
- drawClickableFrag(g, x1, x2, height, bg);
+ drawClickableFrag(g, x1, x2, height, bg, attributes.isHovered());
}
else {
continue;
@@ -885,15 +892,17 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co
g.fillRect(x, y, width, height);
}
- private static void drawClickableFrag(Graphics2D g, float x1, float x2, int height, Color bg) {
+ private static void drawClickableFrag(Graphics2D g, float x1, float x2, int height, Color bg, boolean hovered) {
boolean darcula = UIUtil.isUnderDarcula();
Color c1 = darcula ? bg.brighter() : bg;
Color c2 = darcula ? bg : bg.darker();
GraphicsConfig c = GraphicsUtil.setupRoundedBorderAntialiasing(g);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f));
- g.setPaint(UIUtil.getGradientPaint(x1 + 1, 2, c1, x1 + 1, height - 5, c2));
RoundRectangle2D.Float shape = new RoundRectangle2D.Float(x1 + 1, 2, x2 - x1 - 2, height - 4, 4, 4);
- g.fill(shape);
+ if (hovered) {
+ g.setPaint(UIUtil.getGradientPaint(x1 + 1, 2, c1, x1 + 1, height - 5, c2));
+ g.fill(shape);
+ }
g.setColor(new JBColor(Gray.xCC, new Color(0x757b80)));
g.draw(shape);
c.restore();
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
index 3d6b6132559d..7489aa63bc38 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
@@ -271,7 +271,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
if (myAssigneeVisible) {
myAssigneeCombo = new ComboBox<>();
- myAssigneeCombo.setRenderer((list, value, i, selected, focused) -> new JBLabel(value == null ? "" : value.getDisplayText()));
+ myAssigneeCombo.setRenderer(SimpleListCellRenderer.create("", Developer::getDisplayText));
myAssigneeCombo.setPrototypeDisplayValue(new Developer(0, StringUtil.repeatSymbol('-', 30)));
myAssigneeCombo.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
index 922854cb8833..ee3978a6f8fc 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
@@ -84,6 +84,7 @@ import static javax.swing.KeyStroke.getKeyStroke;
public class Switcher extends AnAction implements DumbAware {
private static final Key SWITCHER_KEY = Key.create("SWITCHER_KEY");
private static final Color SEPARATOR_COLOR = JBColor.namedColor("Popup.separatorColor", new JBColor(Gray.xC0, Gray.x4B));
+ private static final String TOGGLE_CHECK_BOX_ACTION_ID = "SwitcherToggleCheckBox";
private static final int MINIMUM_HEIGHT = JBUI.scale(100);
@@ -143,17 +144,17 @@ public class Switcher extends AnAction implements DumbAware {
SwitcherPanel switcher = SWITCHER_KEY.get(project);
if (switcher != null) {
boolean sameShortcut = Comparing.equal(switcher.myTitle, title);
- if (switcher.isCheckboxMode()) {
- if (sameShortcut) {
+ if (sameShortcut) {
+ if (switcher.isCheckboxMode() && !ToggleCheckBoxAction.isEnabled()) {
switcher.toggleShowEditedFiles();
}
else {
- switcher.setShowOnlyEditedFiles(onlyEdited);
+ switcher.goForward();
}
return null;
}
- else if (sameShortcut) {
- switcher.goForward();
+ else if (switcher.isCheckboxMode()) {
+ switcher.setShowOnlyEditedFiles(onlyEdited);
return null;
}
}
@@ -171,6 +172,27 @@ public class Switcher extends AnAction implements DumbAware {
return switcher;
}
+ public static class ToggleCheckBoxAction extends DumbAwareAction implements DumbAware {
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent e) {
+ Project project = e.getProject();
+ SwitcherPanel switcherPanel = SWITCHER_KEY.get(project);
+ if (switcherPanel != null) {
+ switcherPanel.toggleShowEditedFiles();
+ }
+ }
+
+ @Override
+ public void update(@NotNull AnActionEvent e) {
+ Project project = e.getProject();
+ e.getPresentation().setEnabledAndVisible(SWITCHER_KEY.get(project) != null);
+ }
+
+ static boolean isEnabled() {
+ return getActiveKeymapShortcuts(TOGGLE_CHECK_BOX_ACTION_ID).getShortcuts().length > 0;
+ }
+ }
+
public static class SwitcherPanel extends JPanel implements KeyListener, MouseListener, MouseMotionListener, DataProvider,
QuickSearchComponent {
final JBPopup myPopup;
@@ -188,7 +210,6 @@ public class Switcher extends AnAction implements DumbAware {
final Alarm myAlarm;
final SwitcherSpeedSearch mySpeedSearch;
final String myTitle;
- final String myActionId;
final int myBaseModifier;
private JBPopup myHint;
@@ -293,7 +314,6 @@ public class Switcher extends AnAction implements DumbAware {
setLayout(new SwitcherLayouter());
this.project = project;
myTitle = title;
- myActionId = actionId;
myPinned = pinned;
mySpeedSearch = pinned ? new SwitcherSpeedSearch(this) : null;
@@ -469,7 +489,9 @@ public class Switcher extends AnAction implements DumbAware {
myClickListener.installOn(files);
ScrollingUtil.ensureSelectionExists(files);
- myShowOnlyEditedFilesCheckBox = new MyCheckBox(actionId, onlyEdited);
+ myShowOnlyEditedFilesCheckBox = new MyCheckBox(ToggleCheckBoxAction.isEnabled() ? TOGGLE_CHECK_BOX_ACTION_ID
+ : actionId,
+ onlyEdited);
myTopPanel = createTopPanel(myShowOnlyEditedFilesCheckBox,
isCheckboxMode() ? IdeBundle.message("title.popup.recent.files") : title,
pinned);
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ViewInplaceCommentsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ViewInplaceCommentsAction.java
index deeaff4b1285..0245f52dc8a2 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ViewInplaceCommentsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ViewInplaceCommentsAction.java
@@ -5,8 +5,13 @@ import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAwareToggleAction;
import com.intellij.openapi.wm.impl.IdeBackgroundUtil;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
+import javax.swing.*;
+import java.awt.*;
+
/**
* @author gregsh
*/
@@ -23,6 +28,14 @@ public class ViewInplaceCommentsAction extends DumbAwareToggleAction {
@Override
public void setSelected(@NotNull AnActionEvent e, boolean state) {
UISettings.getInstance().setShowInplaceComments(state);
+ updateAllTreesCellsWidth();
IdeBackgroundUtil.repaintAllWindows();
}
+
+ private static void updateAllTreesCellsWidth() {
+ for (JTree tree : UIUtil.uiTraverser(null).withRoots(Window.getWindows()).filter(JTree.class)) {
+ //noinspection deprecation
+ TreeUtil.invalidateCacheAndRepaint(tree.getUI());
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableNewLayout.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableNewLayout.java
index 51a1bb840b11..920ee4ed2a87 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableNewLayout.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableNewLayout.java
@@ -108,7 +108,7 @@ public class PluginManagerConfigurableNewLayout
private LinkComponent myMarketplaceSortByAction;
private DefaultActionGroup myInstalledSearchGroup;
- private Runnable myInstalledSearchCallback;
+ private Consumer myInstalledSearchCallback;
private boolean myInstalledSearchSetState = true;
@NotNull
@@ -344,10 +344,10 @@ public class PluginManagerConfigurableNewLayout
Map> customRepositoriesMap = pair.second;
try {
- addGroup(groups, allRepositoriesMap, "Featured", "is_featured_search=true", "sortBy:featured");
- addGroup(groups, allRepositoriesMap, "New and Updated", "orderBy=update+date", "sortBy:updated");
- addGroup(groups, allRepositoriesMap, "Top Downloads", "orderBy=downloads", "sortBy:downloads");
- addGroup(groups, allRepositoriesMap, "Top Rated", "orderBy=rating", "sortBy:rating");
+ addGroup(groups, allRepositoriesMap, "Featured", "is_featured_search=true", "/sortBy:featured");
+ addGroup(groups, allRepositoriesMap, "New and Updated", "orderBy=update+date", "/sortBy:updated");
+ addGroup(groups, allRepositoriesMap, "Top Downloads", "orderBy=downloads", "/sortBy:downloads");
+ addGroup(groups, allRepositoriesMap, "Top Rated", "orderBy=rating", "/sortBy:rating");
}
catch (IOException e) {
PluginManagerMain.LOG
@@ -548,8 +548,8 @@ public class PluginManagerConfigurableNewLayout
List queries = new ArrayList<>();
new SearchQueryParser.Marketplace(searchTextField.getText()) {
@Override
- protected void setSearchQuery(@NotNull String query) {
- super.setSearchQuery(query);
+ protected void addToSearchQuery(@NotNull String query) {
+ super.addToSearchQuery(query);
queries.add(query);
}
@@ -858,56 +858,38 @@ public class PluginManagerConfigurableNewLayout
PluginsGroupComponent panel = new PluginsGroupComponent(new PluginListLayout(), new MultiSelectionEventHandler(), myNameListener,
PluginManagerConfigurableNewLayout.this.mySearchListener,
- descriptor -> new NewListPluginComponent(myPluginModel, descriptor,
- false));
+ descriptor -> new NewListPluginComponent(myPluginModel, descriptor, false));
panel.setSelectionListener(selectionListener);
PluginManagerConfigurableNew.registerCopyProvider(panel);
- myInstalledSearchCallback = () -> {
- StringBuilder queryBuilder = new StringBuilder();
-
- for (AnAction action : myInstalledSearchGroup.getChildren(null)) {
- InstalledSearchOptionAction optionAction = (InstalledSearchOptionAction)action;
-
- if (optionAction.myState) {
- if (queryBuilder.length() > 0) {
- queryBuilder.append(" ");
- }
-
- switch (optionAction.myOption) {
- case Enabled:
- queryBuilder.append("/enabled");
- break;
- case Disabled:
- queryBuilder.append("/disabled");
- break;
- case Custom:
- queryBuilder.append("/custom");
- break;
- case Bundled:
- queryBuilder.append("/bundled");
- break;
- case Invalid:
- queryBuilder.append("/invalid");
- break;
- case NeedUpdate:
- queryBuilder.append("/outdated");
- break;
- case Deleted:
- queryBuilder.append("/uninstalled");
- break;
- case NeedRestart:
- queryBuilder.append("/inactive");
- break;
- }
+ myInstalledSearchCallback = updateAction -> {
+ List queries = new ArrayList<>();
+ new SearchQueryParser.InstalledWithVendor(searchTextField.getText()) {
+ @Override
+ protected void addToSearchQuery(@NotNull String query) {
+ super.addToSearchQuery(query);
+ queries.add(query);
}
+
+ @Override
+ protected void handleAttribute(@NotNull String name, @NotNull String value, boolean invert) {
+ super.handleAttribute(name, value, invert);
+ queries.add("/" + name + (value.isEmpty() ? "" : ":" + value));
+ }
+ };
+
+ if (updateAction.myState) {
+ queries.add(updateAction.getQuery());
+ }
+ else {
+ queries.remove(updateAction.getQuery());
}
try {
myInstalledSearchSetState = false;
- String query = queryBuilder.toString();
+ String query = StringUtil.join(queries, " ");
searchTextField.setTextIgnoreEvents(query);
if (query.isEmpty()) {
myInstalledTab.hideSearchPanel();
@@ -1079,7 +1061,7 @@ public class PluginManagerConfigurableNewLayout
@Override
public void setSelected(@NotNull AnActionEvent e, boolean state) {
myState = state;
- myInstalledSearchCallback.run();
+ myInstalledSearchCallback.accept(this);
}
public void setState(@Nullable SearchQueryParser.Installed parser) {
@@ -1115,6 +1097,29 @@ public class PluginManagerConfigurableNewLayout
break;
}
}
+
+ @NotNull
+ public String getQuery() {
+ switch (myOption) {
+ case Enabled:
+ return "/enabled";
+ case Disabled:
+ return "/disabled";
+ case Custom:
+ return "/custom";
+ case Bundled:
+ return "/bundled";
+ case Invalid:
+ return "/invalid";
+ case NeedUpdate:
+ return "/outdated";
+ case Deleted:
+ return "/uninstalled";
+ case NeedRestart:
+ default:
+ return "/inactive";
+ }
+ }
}
private static class GroupByActionGroup extends DefaultActionGroup implements CheckedActionGroup {
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogo.java b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogo.java
index ba44bab91f2c..765776414964 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogo.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogo.java
@@ -14,6 +14,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.ui.JBColor;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.Url;
import com.intellij.util.Urls;
import com.intellij.util.io.HttpRequests;
@@ -51,11 +52,6 @@ public class PluginLogo {
});
}
- @NotNull
- public static Icon getIcon(@NotNull IdeaPluginDescriptor descriptor, int width, int height) {
- return null;
- }
-
@NotNull
public static Icon getIcon(@NotNull IdeaPluginDescriptor descriptor, boolean big, boolean jb, boolean error, boolean disabled) {
return getIcon(descriptor).getIcon(big, jb, error, disabled);
@@ -151,7 +147,7 @@ public class PluginLogo {
}
File[] files = libFile.listFiles();
- if (files == null || files.length == 0) {
+ if (ArrayUtil.isEmpty(files)) {
putIcon(idPlugin, lazyIcon, null, null);
return;
}
@@ -212,8 +208,8 @@ public class PluginLogo {
}
private static boolean tryLoadDirIcons(@NotNull String idPlugin, @NotNull LazyPluginLogoIcon lazyIcon, @NotNull File path) {
- PluginLogoIconProvider light = tryLoadIcon(new File(path, PluginManagerCore.META_INF + PLUGIN_ICON));
- PluginLogoIconProvider dark = tryLoadIcon(new File(path, PluginManagerCore.META_INF + PLUGIN_ICON_DARK));
+ PluginLogoIconProvider light = tryLoadIcon(path, true);
+ PluginLogoIconProvider dark = tryLoadIcon(path, false);
if (light != null || dark != null) {
putIcon(idPlugin, lazyIcon, light, dark);
@@ -231,8 +227,8 @@ public class PluginLogo {
return false;
}
try (ZipFile zipFile = new ZipFile(path)) {
- PluginLogoIconProvider light = tryLoadIcon(zipFile, PLUGIN_ICON);
- PluginLogoIconProvider dark = tryLoadIcon(zipFile, PLUGIN_ICON_DARK);
+ PluginLogoIconProvider light = tryLoadIcon(zipFile, true);
+ PluginLogoIconProvider dark = tryLoadIcon(zipFile, false);
if (put || light != null || dark != null) {
putIcon(idPlugin, lazyIcon, light, dark);
return true;
@@ -283,6 +279,11 @@ public class PluginLogo {
}, ModalityState.any());
}
+ @Nullable
+ private static PluginLogoIconProvider tryLoadIcon(@NotNull File dirFile, boolean light) {
+ return tryLoadIcon(new File(dirFile, getIconFileName(light)));
+ }
+
@Nullable
private static PluginLogoIconProvider tryLoadIcon(@NotNull File iconFile) {
//noinspection IOResourceOpenedButNotSafelyClosed
@@ -290,11 +291,16 @@ public class PluginLogo {
}
@Nullable
- private static PluginLogoIconProvider tryLoadIcon(@NotNull ZipFile zipFile, @NotNull String name) {
- ZipEntry iconEntry = zipFile.getEntry(PluginManagerCore.META_INF + name);
+ private static PluginLogoIconProvider tryLoadIcon(@NotNull ZipFile zipFile, boolean light) {
+ ZipEntry iconEntry = zipFile.getEntry(getIconFileName(light));
return iconEntry == null ? null : loadFileIcon(() -> zipFile.getInputStream(iconEntry));
}
+ @NotNull
+ static String getIconFileName(boolean light) {
+ return PluginManagerCore.META_INF + (light ? PLUGIN_ICON : PLUGIN_ICON_DARK);
+ }
+
@Nullable
private static PluginLogoIconProvider loadFileIcon(@NotNull ThrowableComputable provider) {
try {
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogoApi.java b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogoApi.java
new file mode 100644
index 000000000000..f3464214fb8e
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginLogoApi.java
@@ -0,0 +1,174 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.ide.plugins.newui;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.openapi.application.JetBrainsProtocolHandler;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.IconLoader;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.ui.JBColor;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * @author Alexander Lobas
+ */
+public class PluginLogoApi {
+ /**
+ * Direct load image from local dir or jar based plugin without background task and caches.
+ */
+ @NotNull
+ public static Icon getIcon(@NotNull IdeaPluginDescriptor descriptor, int width, int height, @Nullable Logger logger) {
+ return new PluginLogoApi(width, height, logger).getIcon(descriptor);
+ }
+
+ private final int myWidth;
+ private final int myHeight;
+
+ private final Logger myLogger;
+
+ private PluginLogoApi(int width, int height, @Nullable Logger logger) {
+ myWidth = width;
+ myHeight = height;
+ myLogger = logger;
+ }
+
+ @NotNull
+ private Icon getIcon(@NotNull IdeaPluginDescriptor descriptor) {
+ File path = descriptor.getPath();
+
+ if (path == null) {
+ return getDefaultIcon();
+ }
+
+ if (path.isDirectory()) {
+ if (System.getProperty(JetBrainsProtocolHandler.REQUIRED_PLUGINS_KEY) != null) {
+ Icon icon = tryLoadDirIcon(new File(path, "classes"));
+ if (icon != null) {
+ return icon;
+ }
+ }
+
+ Icon icon = tryLoadDirIcon(path);
+ if (icon != null) {
+ return icon;
+ }
+
+ File libFile = new File(path, "lib");
+ if (!libFile.exists() || !libFile.isDirectory()) {
+ return getDefaultIcon();
+ }
+
+ File[] files = libFile.listFiles();
+ if (ArrayUtil.isEmpty(files)) {
+ return getDefaultIcon();
+ }
+
+ for (File file : files) {
+ Icon dirIcon = tryLoadDirIcon(file);
+ if (dirIcon != null) {
+ return dirIcon;
+ }
+
+ Icon jarIcon = tryLoadJarIcon(file);
+ if (jarIcon != null) {
+ return jarIcon;
+ }
+ }
+ }
+ else {
+ Icon icon = tryLoadJarIcon(path);
+ if (icon != null) {
+ return icon;
+ }
+ }
+
+ return getDefaultIcon();
+ }
+
+ @Nullable
+ private Icon tryLoadDirIcon(@NotNull File path) {
+ boolean light = JBColor.isBright();
+ Icon icon = tryLoadIcon(path, light);
+ return icon == null ? tryLoadIcon(path, !light) : icon;
+ }
+
+ @Nullable
+ private Icon tryLoadJarIcon(@NotNull File path) {
+ if (!FileUtil.isJarOrZip(path) || !path.exists()) {
+ return null;
+ }
+ try (ZipFile zipFile = new ZipFile(path)) {
+ boolean light = JBColor.isBright();
+ Icon icon = tryLoadIcon(zipFile, light);
+ return icon == null ? tryLoadIcon(zipFile, !light) : icon;
+ }
+ catch (Exception e) {
+ if (myLogger != null) {
+ myLogger.error(e);
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private Icon tryLoadIcon(@NotNull File dirFile, boolean light) {
+ try {
+ File iconFile = new File(dirFile, PluginLogo.getIconFileName(light));
+ return iconFile.exists() && iconFile.length() > 0 ? loadFileIcon(new FileInputStream(iconFile)) : null;
+ }
+ catch (IOException e) {
+ if (myLogger != null) {
+ myLogger.error(e);
+ }
+ return null;
+ }
+ }
+
+ @Nullable
+ private Icon tryLoadIcon(@NotNull ZipFile zipFile, boolean light) {
+ try {
+ ZipEntry iconEntry = zipFile.getEntry(PluginLogo.getIconFileName(light));
+ return iconEntry == null ? null : loadFileIcon(zipFile.getInputStream(iconEntry));
+ }
+ catch (IOException e) {
+ if (myLogger != null) {
+ myLogger.error(e);
+ }
+ return null;
+ }
+ }
+
+ @NotNull
+ private Icon loadFileIcon(@NotNull InputStream stream) throws IOException {
+ return HiDPIPluginLogoIcon.loadSVG(stream, myWidth, myHeight);
+ }
+
+ private Icon getDefaultIcon() {
+ if (AllIcons.Plugins.PluginLogo instanceof IconLoader.CachedImageIcon) {
+ URL url = ((IconLoader.CachedImageIcon)AllIcons.Plugins.PluginLogo).getURL();
+ if (url != null) {
+ try {
+ return HiDPIPluginLogoIcon.loadSVG(url.openStream(), myWidth, myHeight);
+ }
+ catch (IOException e) {
+ if (myLogger != null) {
+ myLogger.error(e);
+ }
+ }
+ }
+ }
+ return AllIcons.Plugins.PluginLogo;
+ }
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/newui/SearchQueryParser.java b/platform/platform-impl/src/com/intellij/ide/plugins/newui/SearchQueryParser.java
index d9e9b453d2b7..d0487704e24e 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/newui/SearchQueryParser.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/newui/SearchQueryParser.java
@@ -94,7 +94,7 @@ public abstract class SearchQueryParser {
return;
}
if (size == 1) {
- setSearchQuery(words.get(0));
+ addToSearchQuery(words.get(0));
return;
}
@@ -108,22 +108,23 @@ public abstract class SearchQueryParser {
handleAttribute(name, words.get(index++), invert);
}
else {
- searchQuery = query;
+ addToSearchQuery(query);
return;
}
}
- else if (searchQuery == null) {
- setSearchQuery(name);
- }
else {
- setSearchQuery(query);
- return;
+ addToSearchQuery(name);
}
}
}
- protected void setSearchQuery(@NotNull String query) {
- searchQuery = query;
+ protected void addToSearchQuery(@NotNull String query) {
+ if (searchQuery == null) {
+ searchQuery = query;
+ }
+ else {
+ searchQuery += " " + query;
+ }
}
protected abstract void handleAttribute(@NotNull String name, @NotNull String value, boolean invert);
@@ -244,12 +245,8 @@ public abstract class SearchQueryParser {
else if (word.startsWith("-#")) {
handleAttribute(word.substring(2), "", true);
}
- else if (searchQuery == null) {
- searchQuery = word;
- }
else {
- searchQuery = query;
- break;
+ addToSearchQuery(word);
}
}
parseEnd();
@@ -319,7 +316,7 @@ public abstract class SearchQueryParser {
vendors.add(words.get(index++));
}
else {
- searchQuery = query;
+ addToSearchQuery(query);
break;
}
}
@@ -327,12 +324,8 @@ public abstract class SearchQueryParser {
handleAttribute(name.substring(1), "", false);
}
}
- else if (searchQuery == null) {
- searchQuery = name;
- }
else {
- searchQuery = query;
- break;
+ addToSearchQuery(name);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java
index 29cdff3a3e4d..d3d22f4b9034 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java
@@ -546,7 +546,7 @@ public class AppearanceConfigurable implements SearchableConfigurable {
}
}
- private static class AAListCellRenderer extends JLabel implements ListCellRenderer {
+ private static class AAListCellRenderer extends SimpleListCellRenderer {
private static final Object SUBPIXEL_HINT = GraphicsUtil.createAATextInfo(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
private static final Object GREYSCALE_HINT = GraphicsUtil.createAATextInfo(RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
@@ -557,7 +557,7 @@ public class AppearanceConfigurable implements SearchableConfigurable {
}
@Override
- public Component getListCellRendererComponent(JList extends AntialiasingType> list, AntialiasingType value, int i, boolean s, boolean f) {
+ public void customize(JList extends AntialiasingType> list, AntialiasingType value, int index, boolean selected, boolean hasFocus) {
if (value == AntialiasingType.SUBPIXEL) {
GraphicsUtil.setAntialiasingType(this, SUBPIXEL_HINT);
}
@@ -574,8 +574,6 @@ public class AppearanceConfigurable implements SearchableConfigurable {
}
setText(String.valueOf(value));
-
- return this;
}
}
}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
index cb91f6ee83ea..df88daadf1fd 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
@@ -539,18 +539,26 @@ public final class LafManagerImpl extends LafManager implements PersistentStateC
defaults.put("TreeUI", "com.intellij.ui.tree.ui.DefaultTreeUI");
defaults.put("Tree.repaintWholeRow", true);
}
- Icon collapsedIcon = defaults.getIcon("Tree.collapsedIcon");
- if (collapsedIcon == null || collapsedIcon instanceof UIResource) {
+ if (isUnsupported(defaults.getIcon("Tree.collapsedIcon"))) {
defaults.put("Tree.collapsedIcon", LafIconLookup.getIcon("treeCollapsed"));
defaults.put("Tree.collapsedSelectedIcon", LafIconLookup.getSelectedIcon("treeCollapsed"));
}
- Icon expandedIcon = defaults.getIcon("Tree.expandedIcon");
- if (expandedIcon == null || collapsedIcon instanceof UIResource) {
+ if (isUnsupported(defaults.getIcon("Tree.expandedIcon"))) {
defaults.put("Tree.expandedIcon", LafIconLookup.getIcon("treeExpanded"));
defaults.put("Tree.expandedSelectedIcon", LafIconLookup.getSelectedIcon("treeExpanded"));
}
}
+ /**
+ * @param icon an icon retrieved from L&F
+ * @return {@code true} if an icon is not specified or if it is declared in some Swing L&F
+ * (such icons do not have a variant to paint in selected row)
+ */
+ private static boolean isUnsupported(@Nullable Icon icon) {
+ String name = icon == null ? null : icon.getClass().getName();
+ return name == null || name.startsWith("javax.swing.plaf.") || name.startsWith("com.sun.java.swing.plaf.");
+ }
+
private static void patchHiDPI(UIDefaults defaults) {
Object prevScaleVal = defaults.get("hidpi.scaleFactor");
// used to normalize previously patched values
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
index 659607a77057..9185b800e6a9 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
@@ -207,6 +207,10 @@ Spinner.editorBorderPainted=false
SplitPane.highlight=3c3f41
TreeUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTreeUI
+Tree.collapsedIcon=/com/intellij/ide/ui/laf/icons/darcula/treeCollapsed.svg
+Tree.expandedIcon=/com/intellij/ide/ui/laf/icons/darcula/treeExpanded.svg
+Tree.collapsedSelectedIcon=/com/intellij/ide/ui/laf/icons/darcula/treeCollapsedSelected.svg
+Tree.expandedSelectedIcon=/com/intellij/ide/ui/laf/icons/darcula/treeExpandedSelected.svg
Tree.paintLines=false
Tree.hash=505355
@@ -279,4 +283,8 @@ DragAndDrop.areaBackground=404a57
DragAndDrop.areaBorderColor=4f73a8
DragAndDrop.areaForeground=bababa
-CompletionPopup.nonFocusedState=true
\ No newline at end of file
+CompletionPopup.nonFocusedState=true
+
+NewClass.Panel.background=45494a
+NewClass.SearchField.background=3c3f41
+NewClass.separatorWidth=10
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
index 7863d29e6b83..608865362543 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
@@ -184,6 +184,10 @@ SplitPane.highlight=f2f2f2
TreeUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTreeUI
Tree.background=ffffff
+Tree.collapsedIcon=/com/intellij/ide/ui/laf/icons/intellij/treeCollapsed.svg
+Tree.expandedIcon=/com/intellij/ide/ui/laf/icons/intellij/treeExpanded.svg
+Tree.collapsedSelectedIcon=/com/intellij/ide/ui/laf/icons/intellij/treeCollapsedSelected.svg
+Tree.expandedSelectedIcon=/com/intellij/ide/ui/laf/icons/intellij/treeExpandedSelected.svg
Tree.paintLines=false
Tree.hash=E6E6E6
Tree.textBackground=ffffff
@@ -277,4 +281,8 @@ DragAndDrop.areaBackground=e1ebf5
DragAndDrop.areaBorderColor=8ab2de
DragAndDrop.areaForeground=787878
-CompletionPopup.nonFocusedState=true
\ No newline at end of file
+CompletionPopup.nonFocusedState=true
+
+NewClass.Panel.background=f2f2f2
+NewClass.SearchField.background=ffffff
+NewClass.separatorWidth=10
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties
index ab5768ea381d..280456daaece 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties
@@ -101,6 +101,10 @@ TabbedPane.tabFillStyle=underline
TableHeader.cellBorder=2,2,2,2
+Tree.collapsedIcon=/com/intellij/ide/ui/laf/icons/treeCollapsed.svg
+Tree.expandedIcon=/com/intellij/ide/ui/laf/icons/treeExpanded.svg
+Tree.collapsedSelectedIcon=/com/intellij/ide/ui/laf/icons/treeCollapsedSelected.svg
+Tree.expandedSelectedIcon=/com/intellij/ide/ui/laf/icons/treeExpandedSelected.svg
Tree.paintLines=false
Tree.hash=E6E6E6
Tree.rowHeight=20
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties
index ab4a05f19aab..dea0423e848e 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties
@@ -174,6 +174,10 @@ SearchEverywhere.shortcutForeground=a7c1db
TreeUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTreeUI
Tree.background=ffffff
+Tree.collapsedIcon=/com/intellij/ide/ui/laf/icons/win10/treeCollapsed.svg
+Tree.expandedIcon=/com/intellij/ide/ui/laf/icons/win10/treeExpanded.svg
+Tree.collapsedSelectedIcon=/com/intellij/ide/ui/laf/icons/win10/treeCollapsedSelected.svg
+Tree.expandedSelectedIcon=/com/intellij/ide/ui/laf/icons/win10/treeExpandedSelected.svg
Tree.paintLines=false
Tree.hash=E6E6E6
Tree.rowHeight=0
@@ -264,4 +268,8 @@ SearchEverywhere.SearchField.infoForeground=808080
SearchEverywhere.Advertiser.foreground=808080
SearchEverywhere.Advertiser.background=f2f2f2
-CompletionPopup.nonFocusedState=true
\ No newline at end of file
+CompletionPopup.nonFocusedState=true
+
+NewClass.Panel.background=f2f2f2
+NewClass.SearchField.background=ffffff
+NewClass.separatorWidth=10
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java
index dd4502024f01..fdaed9107432 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java
@@ -1,7 +1,6 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.diff.impl.mergeTool;
-import com.intellij.configurationStore.StoreReloadManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.undo.DocumentReference;
@@ -14,17 +13,12 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.projectImport.ProjectOpenProcessor;
-import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
-import java.util.Collection;
-import java.util.Set;
@Deprecated
public interface MergeVersion {
@@ -88,31 +82,6 @@ public interface MergeVersion {
setDocumentText(myDocument, text, DiffBundle.message("save.merge.result.command.name"), project);
FileDocumentManager.getInstance().saveDocument(myDocument);
- reportProjectFileChangeIfNeeded(project, getFile());
- }
-
- public static void reportProjectFileChangeIfNeeded(@Nullable Project project, @Nullable VirtualFile file) {
- if (project != null && file != null && !file.isDirectory() && (ProjectUtil.isProjectOrWorkspaceFile(file) || isProjectFile(file))) {
- StoreReloadManager.getInstance().saveChangedProjectFile(file, project);
- }
- }
-
- @Nullable
- public static Runnable prepareToReportChangedProjectFiles(@NotNull final Project project, @NotNull Collection extends VirtualFile> files) {
- final Set vfs = new THashSet<>();
- for (VirtualFile file : files) {
- if (file != null && !file.isDirectory()) {
- if (ProjectUtil.isProjectOrWorkspaceFile(file) || isProjectFile(file)) {
- vfs.add(file);
- }
- }
- }
- return vfs.isEmpty() ? null : () -> {
- StoreReloadManager storeReloadManager = StoreReloadManager.getInstance();
- for (VirtualFile vf : vfs) {
- storeReloadManager.saveChangedProjectFile(vf, project);
- }
- };
}
@Override
@@ -120,11 +89,6 @@ public interface MergeVersion {
ApplicationManager.getApplication().runWriteAction(() -> doRestoreOriginalContent(project));
}
- public static boolean isProjectFile(VirtualFile file) {
- final ProjectOpenProcessor importProvider = ProjectOpenProcessor.getImportProvider(file);
- return importProvider != null && importProvider.lookForProjectsInDirectory();
- }
-
protected void doRestoreOriginalContent(@Nullable Project project) {
setDocumentText(myDocument, myTextBeforeMerge, "", project);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
index a41aa9a06531..98a804c06184 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
@@ -591,12 +591,13 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
AffineTransform old = setMirrorTransformIfNeeded(g, getLineNumberAreaOffset(), getLineNumberAreaWidth());
try {
- int caretLine = convertor.execute(myEditor.getCaretModel().getLogicalPosition().line);
+ int caretLogicalLine = myEditor.getCaretModel().getLogicalPosition().line;
VisualLinesIterator visLinesIterator = new VisualLinesIterator(myEditor, startVisualLine);
while (!visLinesIterator.atEnd() && visLinesIterator.getVisualLine() <= endVisualLine) {
if (!visLinesIterator.startsWithSoftWrap()) {
- int logLine = convertor.execute(visLinesIterator.getStartLogicalLine());
- if (logLine >= 0) {
+ int logicalLine = visLinesIterator.getStartLogicalLine();
+ int lineToDisplay = convertor.execute(logicalLine);
+ if (lineToDisplay >= 0) {
int startY = visLinesIterator.getY();
if (myEditor.isInDistractionFreeMode()) {
Color fgColor = myTextFgColors.get(visLinesIterator.getVisualLine());
@@ -605,11 +606,11 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
g.setColor(color);
}
- if (colorUnderCaretRow != null && caretLine == logLine) {
+ if (colorUnderCaretRow != null && caretLogicalLine == logicalLine) {
g.setColor(colorUnderCaretRow);
}
- String s = String.valueOf(logLine + 1);
+ String s = String.valueOf(lineToDisplay + 1);
int textOffset = isMirrored() ?
offset - getLineNumberAreaWidth() - 1 :
offset - g.getFontMetrics().stringWidth(s);
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
index f9161251ecff..c421c10c563c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
@@ -212,7 +212,7 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
- if (expanded != null) control.paint(g, x, y, getIconWidth(), getIconHeight(), expanded, false);
+ if (expanded != null) control.paint(c, g, x, y, getIconWidth(), getIconHeight(), expanded, false);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java
index 2a19a27ee772..aa3193cb524e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java
@@ -14,10 +14,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.ui.popup.util.PopupUtil;
-import com.intellij.openapi.util.ActionCallback;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.WindowStateService;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.ex.LayoutFocusTraversalPolicyExt;
@@ -51,6 +48,7 @@ public class FrameWrapper implements Disposable, DataProvider {
private String myTitle = "";
private List myImages = null;
private boolean myCloseOnEsc = false;
+ private BooleanGetter myOnCloseHandler;
private Window myFrame;
private final Map myDataMap = ContainerUtil.newHashMap();
private Project myProject;
@@ -119,10 +117,17 @@ public class FrameWrapper implements Disposable, DataProvider {
}
if (frame instanceof JFrame) {
- ((JFrame)frame).setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
- } else {
- ((JDialog)frame).setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ ((JFrame)frame).setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
}
+ else {
+ ((JDialog)frame).setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+ }
+ frame.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ close();
+ }
+ });
UIUtil.decorateWindowHeader(((RootPaneContainer)frame).getRootPane());
@@ -180,6 +185,13 @@ public class FrameWrapper implements Disposable, DataProvider {
}
public void close() {
+ if (myOnCloseHandler != null && !myOnCloseHandler.get()) return;
+
+ // if you remove this line problems will start happen on Mac OS X
+ // 2 projects opened, call Cmd+D on the second opened project and then Esc.
+ // Weird situation: 2nd IdeFrame will be active, but focus will be somewhere inside the 1st IdeFrame
+ // App is unusable until Cmd+Tab, Cmd+tab
+ FrameWrapper.this.myFrame.setVisible(false);
Disposer.dispose(this);
}
@@ -240,11 +252,6 @@ public class FrameWrapper implements Disposable, DataProvider {
@Override
public void actionPerformed(ActionEvent e) {
if (!PopupUtil.handleEscKeyEvent()) {
- // if you remove this line problems will start happen on Mac OS X
- // 2 projects opened, call Cmd+D on the second opened project and then Esc.
- // Weird situation: 2nd IdeFrame will be active, but focus will be somewhere inside the 1st IdeFrame
- // App is unusable until Cmd+Tab, Cmd+tab
- FrameWrapper.this.myFrame.setVisible(false);
close();
}
}
@@ -313,6 +320,10 @@ public class FrameWrapper implements Disposable, DataProvider {
myImages = images;
}
+ public void setOnCloseHandler(BooleanGetter onCloseHandler) {
+ myOnCloseHandler = onCloseHandler;
+ }
+
protected void loadFrameState() {
final Window frame = getFrame();
if (myDimensionKey != null && !WindowStateService.getInstance().loadStateFor(myProject, myDimensionKey, frame)) {
@@ -361,7 +372,6 @@ public class FrameWrapper implements Disposable, DataProvider {
MouseGestureManager.getInstance().add(this);
setFocusTraversalPolicy(new LayoutFocusTraversalPolicyExt());
- setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
@Override
@@ -452,7 +462,6 @@ public class FrameWrapper implements Disposable, DataProvider {
setBackground(UIUtil.getPanelBackground());
MouseGestureManager.getInstance().add(this);
setFocusTraversalPolicy(new LayoutFocusTraversalPolicyExt());
- setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java b/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java
index 800dc5786130..5a30f79c0b68 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java
@@ -3,6 +3,7 @@ package com.intellij.openapi.ui;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.WindowWrapper.Mode;
+import com.intellij.openapi.util.BooleanGetter;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
@@ -26,6 +27,7 @@ public class WindowWrapperBuilder {
@Nullable private Computable myPreferredFocusedComponent;
@Nullable private String myDimensionServiceKey;
@Nullable private Runnable myOnShowCallback;
+ @Nullable private BooleanGetter myOnCloseHandler;
public WindowWrapperBuilder(@NotNull Mode mode, @NotNull JComponent component) {
myMode = mode;
@@ -74,6 +76,12 @@ public class WindowWrapperBuilder {
return this;
}
+ @NotNull
+ public WindowWrapperBuilder setOnCloseHandler(@NotNull BooleanGetter handler) {
+ myOnCloseHandler = handler;
+ return this;
+ }
+
@NotNull
public WindowWrapper build() {
switch (myMode) {
@@ -107,7 +115,7 @@ public class WindowWrapperBuilder {
myDialog = builder.myParent != null
? new MyDialogWrapper(builder.myParent, builder.myComponent)
: new MyDialogWrapper(builder.myProject, builder.myComponent);
- myDialog.setParameters(builder.myDimensionServiceKey, builder.myPreferredFocusedComponent);
+ myDialog.setParameters(builder.myDimensionServiceKey, builder.myPreferredFocusedComponent, builder.myOnCloseHandler);
installOnShowCallback(myDialog.getWindow(), builder.myOnShowCallback);
@@ -178,6 +186,7 @@ public class WindowWrapperBuilder {
@NotNull private final JComponent myComponent;
@Nullable private String myDimensionServiceKey;
@Nullable private Computable extends JComponent> myPreferredFocusedComponent;
+ @Nullable private BooleanGetter myOnCloseHandler;
MyDialogWrapper(@Nullable Project project, @NotNull JComponent component) {
super(project, true);
@@ -190,9 +199,11 @@ public class WindowWrapperBuilder {
}
public void setParameters(@Nullable String dimensionServiceKey,
- @Nullable Computable extends JComponent> preferredFocusedComponent) {
+ @Nullable Computable extends JComponent> preferredFocusedComponent,
+ @Nullable BooleanGetter onCloseHandler) {
myDimensionServiceKey = dimensionServiceKey;
myPreferredFocusedComponent = preferredFocusedComponent;
+ myOnCloseHandler = onCloseHandler;
}
@Nullable
@@ -231,6 +242,12 @@ public class WindowWrapperBuilder {
if (myPreferredFocusedComponent != null) return myPreferredFocusedComponent.compute();
return super.getPreferredFocusedComponent();
}
+
+ @Override
+ public void doCancelAction() {
+ if (myOnCloseHandler != null && !myOnCloseHandler.get()) return;
+ super.doCancelAction();
+ }
}
}
@@ -251,6 +268,7 @@ public class WindowWrapperBuilder {
myFrame = new MyFrameWrapper(builder.myProject, builder.myDimensionServiceKey);
myFrame.setParameters(builder.myPreferredFocusedComponent);
+ myFrame.setOnCloseHandler(builder.myOnCloseHandler);
myOnShowCallback = builder.myOnShowCallback;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java
index 296edf3b41f4..93c906557c19 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java
@@ -81,7 +81,7 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
myEventCounter.eventHappened(session);
}
- private void doScan(RefreshSessionImpl session) {
+ private void doScan(@NotNull RefreshSessionImpl session) {
try {
updateSessionMap(session, true);
session.scan();
@@ -91,7 +91,7 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
}
}
- private void updateSessionMap(RefreshSession session, boolean add) {
+ private void updateSessionMap(@NotNull RefreshSession session, boolean add) {
long id = session.getId();
if (id != 0) {
synchronized (mySessions) {
@@ -135,5 +135,9 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
}
@Override
- public void dispose() { }
+ public void dispose() {
+ synchronized (mySessions) {
+ mySessions.forEachValue(session -> { ((RefreshSessionImpl)session).cancel(); return true; });
+ }
+ }
}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java
index 87a55a0130e5..bc69bf3dbe73 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java
@@ -144,6 +144,7 @@ public class RefreshWorker {
@NotNull TObjectHashingStrategy strategy,
@NotNull VirtualDirectoryImpl dir) {
while (true) {
+ checkCancelled(dir);
// obtaining directory snapshot
Pair result = LocalFileSystemRefreshWorker.getDirectorySnapshot(persistence, dir);
if (result == null) return;
@@ -189,6 +190,7 @@ public class RefreshWorker {
// generating events unless a directory was changed in between
boolean hasEvents = ReadAction.compute(() -> {
+ checkCancelled(dir);
if (!Arrays.equals(persistedNames, persistence.list(dir)) || !Arrays.equals(children, dir.getChildren())) {
if (LOG.isTraceEnabled()) LOG.trace("retry: " + dir);
return false;
@@ -206,6 +208,7 @@ public class RefreshWorker {
}
for (Pair pair : updatedMap) {
+ checkCancelled(dir);
VirtualFile child = pair.first;
FileAttributes childAttributes = pair.second;
if (childAttributes != null) {
@@ -229,6 +232,7 @@ public class RefreshWorker {
@NotNull TObjectHashingStrategy strategy,
@NotNull VirtualDirectoryImpl dir) {
while (true) {
+ checkCancelled(dir);
// obtaining directory snapshot
Pair, List> result =
ReadAction.compute(() -> pair(dir.getCachedChildren(), dir.getSuspiciousNames()));
@@ -263,6 +267,7 @@ public class RefreshWorker {
// generating events unless a directory was changed in between
boolean hasEvents = ReadAction.compute(() -> {
+ checkCancelled(dir);
if (!cached.equals(dir.getCachedChildren()) || !wanted.equals(dir.getSuspiciousNames())) {
if (LOG.isTraceEnabled()) LOG.trace("retry: " + dir);
return false;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt
index 11ee9c6171e8..a21598be3d3b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/customFrameDecorations/header/CustomHeader.kt
@@ -5,6 +5,7 @@ import com.intellij.icons.AllIcons
import com.intellij.jdkEx.JdkEx
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
+import com.intellij.openapi.util.io.WindowsRegistryUtil
import com.intellij.openapi.wm.impl.IdeRootPane
import com.intellij.openapi.wm.impl.customFrameDecorations.CustomFrameTitleButtons
import com.intellij.ui.AppUIUtil
@@ -97,7 +98,7 @@ abstract class CustomHeader(private val window: Window) : JPanel(), Disposable {
onClose()
}
- override fun windowStateChanged(e: java.awt.event.WindowEvent?) {
+ override fun windowStateChanged(e: WindowEvent?) {
windowStateChanged()
}
}
@@ -216,9 +217,12 @@ abstract class CustomHeader(private val window: Window) : JPanel(), Disposable {
inner class CustomFrameTopBorder(val isTopNeeded: ()-> Boolean = {true}, val isBottomNeeded: ()-> Boolean = {false}) : Border {
val thickness = 1
private val menuBarBorderColor: Color = JBColor.namedColor("MenuBar.borderColor", JBColor(Gray.xCD, Gray.x51))
+ private val affectsBorders: Boolean = Toolkit.getDefaultToolkit().getDesktopProperty("win.dwm.colorizationColor.affects.borders") as Boolean? ?: true
private val activeColor = Toolkit.getDefaultToolkit().getDesktopProperty("win.dwm.colorizationColor") as Color? ?:
Toolkit.getDefaultToolkit().getDesktopProperty("win.frame.activeBorderColor") as Color? ?: menuBarBorderColor
+ private val windowsVersion = WindowsRegistryUtil.readRegistryValue("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ReleaseId")
+
fun repaintBorder() {
val borderInsets = getBorderInsets(this@CustomHeader)
@@ -227,7 +231,7 @@ abstract class CustomHeader(private val window: Window) : JPanel(), Disposable {
}
override fun paintBorder(c: Component, g: Graphics, x: Int, y: Int, width: Int, height: Int) {
- if (isTopNeeded() && myActive) {
+ if (isTopNeeded() && myActive && isAffectsBorder()) {
g.color = activeColor
LinePainter2D.paint(g as Graphics2D, x.toDouble(), y.toDouble(), width.toDouble(), y.toDouble())
}
@@ -239,9 +243,16 @@ abstract class CustomHeader(private val window: Window) : JPanel(), Disposable {
}
}
+ private fun isAffectsBorder(): Boolean {
+ if(windowsVersion.isNullOrEmpty()) return true
+
+ val winVersion = windowsVersion.toIntOrNull() ?: return affectsBorders
+ return if(winVersion >= 1809) affectsBorders else true
+ }
+
override fun getBorderInsets(c: Component): Insets {
val scale = JBUI.scale(thickness)
- return Insets(if (isTopNeeded()) thickness else 0, 0, if (isBottomNeeded()) scale else 0, 0)
+ return Insets(if (isTopNeeded() && isAffectsBorder()) thickness else 0, 0, if (isBottomNeeded()) scale else 0, 0)
}
override fun isBorderOpaque(): Boolean {
diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/ClassicPainter.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/ClassicPainter.java
index e71ff6f2a7d0..0cdd69290578 100644
--- a/platform/platform-impl/src/com/intellij/ui/tree/ui/ClassicPainter.java
+++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/ClassicPainter.java
@@ -8,6 +8,7 @@ import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
@@ -50,7 +51,7 @@ final class ClassicPainter implements Control.Painter {
}
@Override
- public void paint(@NotNull Graphics g, int x, int y, int width, int height,
+ public void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height,
@NotNull Control control, int depth, boolean leaf, boolean expanded, boolean selected) {
if (depth <= 0) return; // do not paint
boolean paintLines = getPaintLines();
@@ -72,7 +73,7 @@ final class ClassicPainter implements Control.Painter {
}
}
if (leaf) return; // do not paint control for a leaf node
- control.paint(g, controlX, y, controlWidth, height, expanded, selected);
+ control.paint(c, g, controlX, y, controlWidth, height, expanded, selected);
}
private boolean getPaintLines() {
diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/CompactPainter.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/CompactPainter.java
index 3b342274b2db..8775a5c61cca 100644
--- a/platform/platform-impl/src/com/intellij/ui/tree/ui/CompactPainter.java
+++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/CompactPainter.java
@@ -5,6 +5,7 @@ import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.awt.Component;
import java.awt.Graphics;
final class CompactPainter implements Control.Painter {
@@ -39,7 +40,7 @@ final class CompactPainter implements Control.Painter {
}
@Override
- public void paint(@NotNull Graphics g, int x, int y, int width, int height,
+ public void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height,
@NotNull Control control, int depth, boolean leaf, boolean expanded, boolean selected) {
if (depth <= 0) return; // do not paint
if (!paintLines && leaf) return; // nothing to paint
@@ -61,7 +62,7 @@ final class CompactPainter implements Control.Painter {
}
}
if (leaf) return; // do not paint control for a leaf node
- control.paint(g, controlX, y, controlWidth, height, expanded, selected);
+ control.paint(c, g, controlX, y, controlWidth, height, expanded, selected);
}
private int getLeftIndent() {
diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/Control.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/Control.java
index e9b62a20c0d7..4f71ffa843a6 100644
--- a/platform/platform-impl/src/com/intellij/ui/tree/ui/Control.java
+++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/Control.java
@@ -4,6 +4,7 @@ package com.intellij.ui.tree.ui;
import com.intellij.ui.JBColor;
import org.jetbrains.annotations.NotNull;
+import java.awt.Component;
import java.awt.Graphics;
import javax.swing.Icon;
@@ -15,7 +16,7 @@ public interface Control {
int getHeight();
- void paint(@NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected);
+ void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected);
interface Painter {
@@ -25,7 +26,7 @@ public interface Control {
int getControlOffset(@NotNull Control control, int depth, boolean leaf);
- void paint(@NotNull Graphics g, int x, int y, int width, int height,
+ void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height,
@NotNull Control control, int depth, boolean leaf, boolean expanded, boolean selected);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultControl.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultControl.java
index e2b767527d87..3696c9bf5a9c 100644
--- a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultControl.java
+++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultControl.java
@@ -4,6 +4,7 @@ package com.intellij.ui.tree.ui;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
+import java.awt.Component;
import java.awt.Graphics;
import javax.swing.Icon;
@@ -36,7 +37,7 @@ public final class DefaultControl implements Control {
}
@Override
- public void paint(@NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected) {
+ public void paint(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height, boolean expanded, boolean selected) {
Icon icon = getIcon(expanded, selected);
icon.paintIcon(null, g,
x + (width - icon.getIconWidth()) / 2,
diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java
index 97f4616d3f1c..1450493d5ed1 100644
--- a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java
+++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java
@@ -210,7 +210,7 @@ public final class DefaultTreeUI extends BasicTreeUI {
g.fillRect(viewportX, bounds.y, viewportWidth, bounds.height);
}
int offset = painter.getRendererOffset(control, depth, leaf);
- painter.paint(g, insets.left, bounds.y, offset, bounds.height, control, depth, leaf, expanded, selected && focused);
+ painter.paint(tree, g, insets.left, bounds.y, offset, bounds.height, control, depth, leaf, expanded, selected && focused);
// TODO: editingComponent, editingRow ???
if (editingComponent == null || editingRow != row) {
int width = viewportX + viewportWidth - insets.left - offset - vsbWidth;
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
index aa611a4a96d2..09f0cd19857f 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
@@ -579,7 +579,7 @@
Second Cmd/Ctrl+E switches to Recently Edited Files
-