Merge remote-tracking branch 'origin/master'
authorAlexander Kirillin <Alexander.Kirillin@jetbrains.com>
Tue, 30 Apr 2019 13:53:07 +0000 (16:53 +0300)
committerintellij-monorepo-bot <intellij-monorepo-bot-no-reply@jetbrains.com>
Thu, 2 May 2019 23:41:27 +0000 (02:41 +0300)
GitOrigin-RevId: 6a16531d9dd405767883a6ce82d04513098372e1

298 files changed:
.idea/libraries/kotlin_reflect.xml
.idea/libraries/kotlin_script_runtime.xml
.idea/libraries/kotlin_stdlib_jdk8.xml
.idea/libraries/kotlin_test.xml
java/compiler/tests/com/intellij/compiler/artifacts/ui/ArtifactEditorTestCase.java
java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java
java/execution/impl/src/com/intellij/execution/testDiscovery/indices/TestFilesIndex.java
java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java
java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/UIRootConfigurationAccessor.java
java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java
java/idea-ui/testSrc/com/intellij/ide/projectWizard/RemoteTemplatesTest.java
java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractReturnValue.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingDfaMemoryState.java
java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingRunner.java
java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
java/java-impl/src/META-INF/JavaPlugin.xml
java/java-impl/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java
java/java-impl/src/com/intellij/codeInspection/ExplicitMinMaxCheckInspection.java [new file with mode: 0644]
java/java-impl/src/com/intellij/codeInspection/dataFlow/fix/FindDfaProblemCauseFix.java
java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultSymbolNavigationContributor.java
java/java-impl/src/com/intellij/lang/java/actions/RangeExpression.kt
java/java-impl/src/com/intellij/refactoring/actions/InheritanceToDelegationAction.java
java/java-impl/src/com/intellij/refactoring/actions/RefactoringActionContextUtil.java [new file with mode: 0644]
java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithBuilderAction.java
java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithFactoryAction.java
java/java-impl/src/com/intellij/refactoring/actions/TurnRefsToSuperAction.java
java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerHandler.java
java/java-impl/src/com/intellij/testIntegration/TestIntegrationUtils.java
java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java
java/java-impl/src/inspectionDescriptions/ExplicitMinMaxCheck.html [new file with mode: 0644]
java/java-psi-api/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java
java/java-tests/testData/inspection/dataFlow/tracker/AndChainCause.java
java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNotNull.java [new file with mode: 0644]
java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNumeric.java [new file with mode: 0644]
java/java-tests/testData/inspection/dataFlow/tracker/AssignTrue.java
java/java-tests/testData/inspection/dataFlow/tracker/AssignmentChain.java
java/java-tests/testData/inspection/dataFlow/tracker/BooleanReassignedMultipleTimes.java
java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNull.java
java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNullReassign.java
java/java-tests/testData/inspection/dataFlow/tracker/IndexOfPlusOne.java
java/java-tests/testData/inspection/dataFlow/tracker/NotNullAnnotated.java
java/java-tests/testData/inspection/dataFlow/tracker/NotNullAssignmentInside.java
java/java-tests/testData/inspection/dataFlow/tracker/NotNullObvious.java
java/java-tests/testData/inspection/dataFlow/tracker/NotNullParameterAssigned.java
java/java-tests/testData/inspection/dataFlow/tracker/NpeAnnotation.java
java/java-tests/testData/inspection/dataFlow/tracker/NpeWithCast.java
java/java-tests/testData/inspection/dataFlow/tracker/NullWasChecked.java
java/java-tests/testData/inspection/dataFlow/tracker/NullWasCheckedNullAssigned.java
java/java-tests/testData/inspection/dataFlow/tracker/OrChainCause.java
java/java-tests/testData/inspection/dataFlow/tracker/TrivialContract.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/afterAssignmentInReturn.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/afterConditional.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/afterIf.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/afterInnerConditional.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/afterReturnFromIf.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/afterSwitchInIf.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/beforeAssignmentInReturn.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/beforeConditional.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/beforeIf.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/beforeInnerConditional.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/beforeReturnFromIf.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/beforeSideEffect.java [new file with mode: 0644]
java/java-tests/testData/inspection/explicitMinMaxCheck/beforeSwitchInIf.java [new file with mode: 0644]
java/java-tests/testData/refactoring/anonymousToInner/redundantTypeParameter.java [new file with mode: 0644]
java/java-tests/testData/refactoring/anonymousToInner/redundantTypeParameter_after.java [new file with mode: 0644]
java/java-tests/testData/refactoring/anonymousToInner/requiredTypeParameter.java [new file with mode: 0644]
java/java-tests/testData/refactoring/anonymousToInner/requiredTypeParameter_after.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTrackerTest.java
java/java-tests/testSrc/com/intellij/java/codeInspection/ExplicitMinMaxCheckInspectionTest.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/java/navigation/GotoImplementationHandlerTest.java
java/java-tests/testSrc/com/intellij/java/refactoring/AnonymousToInnerTest.java
java/java-tests/testSrc/com/intellij/openapi/command/undo/EditorTypingAndNavigationUndoTest.java
java/java-tests/testSrc/com/intellij/openapi/command/undo/GlobalUndoTest.java
java/java-tests/testSrc/com/intellij/testIntegration/GenerateMissedTestsTest.java [new file with mode: 0644]
java/testFramework/src/com/intellij/ide/projectWizard/ProjectWizardTestCase.java
jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkReference.java
jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java
jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java
json/src/jsonSchema/build.xml
jvm/jvm-analysis-api/src/com/intellij/codeInspection/NlsCapitalizationUtil.java [new file with mode: 0644]
jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/NlsCapitalizationUtilTest.java [new file with mode: 0644]
platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildContext.groovy
platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildOptions.groovy
platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy
platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy
platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/logging/BuildMessagesImpl.groovy
platform/build-scripts/icons/intellij.platform.images.build.iml
platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/sync/checkIcons.kt
platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/sync/gitUtils.kt
platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/sync/reportUtils.kt
platform/built-in-server/src/org/jetbrains/ide/OpenFileHttpService.kt
platform/built-in-server/src/org/jetbrains/ide/OpenSettingsJbProtocolService.kt [new file with mode: 0644]
platform/built-in-server/src/org/jetbrains/ide/RestService.java [deleted file]
platform/built-in-server/src/org/jetbrains/ide/RestService.kt [new file with mode: 0644]
platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java
platform/core-api/src/com/intellij/openapi/util/ClassExtension.java
platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java
platform/core-impl/src/com/intellij/diagnostic/PerformanceWatcher.java
platform/credential-store/test/PgpTest.kt
platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java
platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemImportingTestCase.java
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/ExternalSystemException.java
platform/lang-api/src/com/intellij/codeInsight/template/Expression.java
platform/lang-api/src/com/intellij/codeInsight/template/impl/TextExpression.java
platform/lang-api/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereContributor.java
platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java
platform/lang-api/src/com/intellij/openapi/projectRoots/SdkModel.java
platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java
platform/lang-impl/src/com/intellij/application/options/CodeStyleAbstractPanel.java
platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/group/ArrangementGroupingRulesControl.java
platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form
platform/lang-impl/src/com/intellij/build/AbstractViewManager.java
platform/lang-impl/src/com/intellij/build/BuildTreeConsoleView.java
platform/lang-impl/src/com/intellij/build/BuildView.java
platform/lang-impl/src/com/intellij/build/ExecutionNode.java
platform/lang-impl/src/com/intellij/build/Filterable.java
platform/lang-impl/src/com/intellij/build/ShowExecutionErrorsOnlyAction.java [deleted file]
platform/lang-impl/src/com/intellij/build/buildTreeFilters.kt [new file with mode: 0644]
platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java
platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/EmptyExpression.java
platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionHintComponent.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/ConstantNode.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/EmptyNode.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/SelectionNode.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/VariableNode.java
platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.java
platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java
platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java
platform/lang-impl/src/com/intellij/ide/actions/GotoSymbolAction.java
platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java
platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/ClassSearchEverywhereContributor.java
platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java
platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SymbolSearchEverywhereContributor.java
platform/lang-impl/src/com/intellij/ide/extensionResources/ExtensionsRootType.java
platform/lang-impl/src/com/intellij/ide/extensionResources/RestoreBundledExtensionsAction.java
platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java
platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultFileNavigationContributor.java
platform/lang-impl/src/com/intellij/ide/util/projectWizard/ProjectSettingsStepBase.java
platform/lang-impl/src/com/intellij/navigation/ChooseByNameContributorEx.java
platform/lang-impl/src/com/intellij/navigation/JBProtocolNavigateCommand.kt
platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectSdksModel.java
platform/lang-impl/src/com/intellij/openapi/util/objectTree/DisposerDebugger.java
platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingForwardIndexAccessor.java
platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MyLookupExpression.java
platform/lang-impl/src/com/intellij/util/indexing/FindSymbolParameters.java
platform/lang-impl/src/com/intellij/util/indexing/HashIdForwardIndexAccessor.java
platform/lang-impl/src/com/intellij/util/indexing/HashedInputData.java [deleted file]
platform/lang-impl/src/com/intellij/util/indexing/SharedMapForwardIndex.java
platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappingIndex.java
platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappings.java
platform/lang-impl/src/com/intellij/util/indexing/UpdatableSnapshotInputMappingIndex.java
platform/lang-impl/src/com/intellij/util/indexing/VfsAwareMapReduceIndex.java
platform/platform-api/src/com/intellij/ide/ui/search/ConfigurableHit.java [deleted file]
platform/platform-api/src/com/intellij/ide/ui/search/ConfigurableHit.kt [new file with mode: 0644]
platform/platform-api/src/com/intellij/ide/ui/search/SearchableOptionsRegistrar.java
platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java
platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java
platform/platform-api/src/com/intellij/openapi/ui/TestDialog.java
platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java
platform/platform-api/src/com/intellij/ui/speedSearch/ElementFilter.java
platform/platform-api/src/com/intellij/ui/tabs/newImpl/TabLabel.java
platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java
platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java
platform/platform-impl/src/com/intellij/diagnostic/IdeaFreezeReporter.java
platform/platform-impl/src/com/intellij/execution/wsl/WSLDistributionLegacy.java
platform/platform-impl/src/com/intellij/ide/AppLifecycleListener.java
platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java
platform/platform-impl/src/com/intellij/ide/IdePopupManager.java
platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java
platform/platform-impl/src/com/intellij/ide/actions/ProjectViewEditSourceAction.kt [new file with mode: 0644]
platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java
platform/platform-impl/src/com/intellij/ide/ui/ConfigurableOptionsTopHitProvider.java
platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java
platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java
platform/platform-impl/src/com/intellij/idea/IdeaApplication.java
platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/SensitiveDataValidator.java
platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/ValidationResultType.java
platform/platform-impl/src/com/intellij/internal/statistic/updater/StatisticsJobsScheduler.java
platform/platform-impl/src/com/intellij/openapi/application/JBProtocolCommand.java
platform/platform-impl/src/com/intellij/openapi/application/JBProtocolShutdownCommand.java
platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSaverDialogImpl.java
platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java
platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java
platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableVisitor.java
platform/platform-impl/src/com/intellij/openapi/options/ex/Settings.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/AbstractEditor.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/ConfigurableEditor.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/ISettingsTreeViewFactory.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorColleague.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorContext.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialog.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialogFactory.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsEditor.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java
platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
platform/platform-impl/src/com/intellij/openapi/project/impl/JBProtocolOpenProjectCommand.java
platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java
platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java
platform/platform-impl/src/com/intellij/platform/PlatformProjectStarter.java
platform/platform-impl/src/com/intellij/ui/CustomProtocolHandler.java
platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java
platform/platform-impl/src/org/jetbrains/io/Responses.kt
platform/platform-resources-en/src/messages/ApplicationBundle.properties
platform/platform-resources-en/src/messages/IdeBundle.properties
platform/platform-resources-en/src/messages/InspectionsBundle.properties
platform/platform-resources-en/src/messages/OptionsBundle.properties
platform/platform-resources/src/META-INF/built-in-server.xml
platform/platform-resources/src/brokenPlugins.txt
platform/platform-resources/src/idea/LangActions.xml
platform/platform-tests/testSrc/com/intellij/execution/wsl/WSLUtilTest.java
platform/platform-tests/testSrc/com/intellij/ide/util/treeView/FilteringTreeBuilderTest.java
platform/platform-tests/testSrc/com/intellij/idea/LockSupportTest.java
platform/platform-tests/testSrc/com/intellij/internal/statistics/SensitiveDataValidatorTest.kt
platform/platform-tests/testSrc/com/intellij/openapi/vfs/encoding/FileEncodingTest.java
platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.kt
platform/platform-tests/testSrc/com/intellij/search/SearchableOptionsTest.java
platform/platform-tests/testSrc/com/intellij/ui/mac/touchbar/NSTLibTest.java
platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewTest.java
platform/platform-tests/testSrc/com/intellij/util/JdkBundleTest.java
platform/projectModel-impl/src/com/intellij/project/model/impl/module/JpsOrderEntryFactory.java [deleted file]
platform/projectModel-impl/src/com/intellij/project/model/impl/module/JpsRootModel.java
platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsExportableOrderEntry.java [deleted file]
platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsInheritedSdkOrderEntry.java [deleted file]
platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsLibraryOrderEntry.java [deleted file]
platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleOrderEntry.java [deleted file]
platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleSdkOrderEntry.java [deleted file]
platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleSourceOrderEntry.java [deleted file]
platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsOrderEntry.java [deleted file]
platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsSdkOrderEntryBase.java [deleted file]
platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
platform/testFramework/src/com/intellij/testFramework/propertyBased/MadTestingUtil.java
platform/testGuiFramework/src/com/intellij/testGuiFramework/fixtures/EditorTabsFixture.kt
platform/testGuiFramework/src/com/intellij/testGuiFramework/util/RepeatUtils.kt
platform/util/src/com/intellij/openapi/application/JetBrainsProtocolHandler.java
platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java
platform/util/src/com/intellij/util/indexing/impl/InputData.java [deleted file]
platform/util/src/com/intellij/util/indexing/impl/MapReduceIndex.java
platform/util/src/com/intellij/util/indexing/impl/forward/AbstractForwardIndexAccessor.java
platform/util/src/com/intellij/util/indexing/impl/forward/AbstractMapForwardIndexAccessor.java
platform/util/src/com/intellij/util/indexing/impl/forward/ForwardIndexAccessor.java
platform/util/src/com/intellij/util/indexing/impl/forward/IntForwardIndexAccessor.java
platform/util/src/com/intellij/util/indexing/impl/forward/KeyCollectionForwardIndexAccessor.java
platform/util/src/com/intellij/util/indexing/impl/forward/MapForwardIndexAccessor.java
platform/util/src/com/intellij/util/ui/UIUtil.java
platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java
platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CopyRevisionNumberFromAnnotateAction.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdateRequestsQueue.java
platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/JBProtocolCheckoutCommand.java
platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsChangesLazilyParsedDetails.java
plugins/devkit/devkit-core/resources/META-INF/plugin.xml
plugins/devkit/devkit-core/resources/inspectionDescriptions/PluginXmlCapitalization.html [new file with mode: 0644]
plugins/devkit/devkit-core/resources/org/jetbrains/idea/devkit/DevKitBundle.properties
plugins/devkit/devkit-core/src/inspections/PluginXmlCapitalizationInspection.java [new file with mode: 0644]
plugins/devkit/devkit-core/src/projectRoots/IdeaJdk.java
plugins/devkit/devkit-java-tests/testData/inspections/pluginXmlCapitalization/pluginXmlCapitalization_Action.xml [new file with mode: 0644]
plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/PluginXmlCapitalizationInspectionTest.java [new file with mode: 0644]
plugins/git4idea/src/git4idea/GitCommit.java
plugins/git4idea/src/git4idea/GitContentRevision.java
plugins/git4idea/src/git4idea/GitStatisticsCollector.kt
plugins/git4idea/src/git4idea/branch/GitRebaseParams.java [deleted file]
plugins/git4idea/src/git4idea/branch/GitRebaseParams.kt [new file with mode: 0644]
plugins/git4idea/src/git4idea/changes/GitChangeUtils.java
plugins/git4idea/src/git4idea/config/GitVcsPanel.java
plugins/git4idea/src/git4idea/config/GitVcsSettings.java
plugins/git4idea/src/git4idea/history/GitChangesParser.java
plugins/git4idea/src/git4idea/push/GitPushOperation.java
plugins/git4idea/src/git4idea/rebase/GitRewordOperation.kt
plugins/git4idea/src/git4idea/status/GitChangesCollector.java
plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java
plugins/git4idea/src/git4idea/update/GitUpdateOptionsPanel.java
plugins/git4idea/tests/git4idea/config/GitExecutableDetectorWindowsTest.java
plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.kt
plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt
plugins/gradle/src/org/jetbrains/plugins/gradle/service/execution/GradleExecutionHelper.java
plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DistributionFactoryExt.java
plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java
plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/WorkCounter.kt
plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/WorkingTimeMeasurer.java [moved from java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/WorkingTimeMeasurer.java with 56% similarity]
plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/uast/GroovyUastPlugin.kt
plugins/java-i18n/intellij.java.i18n.iml
plugins/java-i18n/src/com/intellij/codeInspection/capitalization/TitleCapitalizationInspection.java
plugins/java-i18n/testSrc/com/intellij/codeInspection/CapitalizationTest.java [deleted file]
plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/buildtool/BuildViewMavenConsole.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfiguration.java
python/testSrc/com/jetbrains/env/PyEnvTestCase.java
updater/testSrc/com/intellij/updater/PatchApplyingRevertingTest.java
xml/impl/src/com/intellij/lang/html/HtmlQuotesFormatPreprocessor.java

index adfb20e81e6b28d66f552f62c719cf70e24961ac..bd7fe596a40877a68a719a1501a2b7e4780faf98 100644 (file)
@@ -1,16 +1,16 @@
 <component name="libraryTable">
   <library name="kotlin-reflect" type="repository">
-    <properties maven-id="org.jetbrains.kotlin:kotlin-reflect:1.3.11">
+    <properties maven-id="org.jetbrains.kotlin:kotlin-reflect:1.3.31">
       <exclude>
         <dependency maven-id="org.jetbrains.kotlin:kotlin-stdlib" />
       </exclude>
     </properties>
     <CLASSES>
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.3.11/kotlin-reflect-1.3.11.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.3.31/kotlin-reflect-1.3.31.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.3.11/kotlin-reflect-1.3.11-sources.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.3.31/kotlin-reflect-1.3.31-sources.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
index 22ac358c7be896ba64188b68f2334433e1b682b4..f9d4689132d5c8afc1d037b45af469105b3b4dae 100644 (file)
@@ -1,12 +1,12 @@
 <component name="libraryTable">
   <library name="kotlin-script-runtime" type="repository">
-    <properties maven-id="org.jetbrains.kotlin:kotlin-script-runtime:1.3.11" />
+    <properties maven-id="org.jetbrains.kotlin:kotlin-script-runtime:1.3.31" />
     <CLASSES>
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-script-runtime/1.3.11/kotlin-script-runtime-1.3.11.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-script-runtime/1.3.31/kotlin-script-runtime-1.3.31.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-script-runtime/1.3.11/kotlin-script-runtime-1.3.11-sources.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-script-runtime/1.3.31/kotlin-script-runtime-1.3.31-sources.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
index f4237cb7d370c540673189b9520ecad87c524ee0..3d669e6dc5bf72fa88e77941aa8a189b9e6d61da 100644 (file)
@@ -1,22 +1,22 @@
 <component name="libraryTable">
   <library name="kotlin-stdlib-jdk8" type="repository">
-    <properties maven-id="org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.11">
+    <properties maven-id="org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.31">
       <exclude>
         <dependency maven-id="org.jetbrains:annotations" />
       </exclude>
     </properties>
     <CLASSES>
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.11/kotlin-stdlib-jdk8-1.3.11.jar!/" />
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.3.11/kotlin-stdlib-1.3.11.jar!/" />
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.11/kotlin-stdlib-common-1.3.11.jar!/" />
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.11/kotlin-stdlib-jdk7-1.3.11.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.31/kotlin-stdlib-jdk8-1.3.31.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.3.31/kotlin-stdlib-1.3.31.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.31/kotlin-stdlib-common-1.3.31.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.31/kotlin-stdlib-jdk7-1.3.31.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.11/kotlin-stdlib-jdk8-1.3.11-sources.jar!/" />
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.3.11/kotlin-stdlib-1.3.11-sources.jar!/" />
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.11/kotlin-stdlib-common-1.3.11-sources.jar!/" />
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.11/kotlin-stdlib-jdk7-1.3.11-sources.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.31/kotlin-stdlib-jdk8-1.3.31-sources.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.3.31/kotlin-stdlib-1.3.31-sources.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.31/kotlin-stdlib-common-1.3.31-sources.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.31/kotlin-stdlib-jdk7-1.3.31-sources.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
index 461a3a9ecdc472da8c7507f3df903a976ab52a31..561f37b162085bb325f04415692e0d6854a3d265 100644 (file)
@@ -1,19 +1,19 @@
 <component name="libraryTable">
   <library name="kotlin-test" type="repository">
-    <properties maven-id="org.jetbrains.kotlin:kotlin-test:1.3.11">
+    <properties maven-id="org.jetbrains.kotlin:kotlin-test:1.3.31">
       <exclude>
         <dependency maven-id="org.jetbrains.kotlin:kotlin-stdlib-common" />
         <dependency maven-id="org.jetbrains.kotlin:kotlin-stdlib" />
       </exclude>
     </properties>
     <CLASSES>
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test/1.3.11/kotlin-test-1.3.11.jar!/" />
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test-common/1.3.11/kotlin-test-common-1.3.11.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test/1.3.31/kotlin-test-1.3.31.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test-common/1.3.31/kotlin-test-common-1.3.31.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test/1.3.11/kotlin-test-1.3.11-sources.jar!/" />
-      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test-common/1.3.11/kotlin-test-common-1.3.11-sources.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test/1.3.31/kotlin-test-1.3.31-sources.jar!/" />
+      <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test-common/1.3.31/kotlin-test-common-1.3.31-sources.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
index 3c74644ece14ab919829a9a27e064d0aa3cd1df0..9b18c4aa0e3a743050190a1d60b4c6f29cc21da8 100644 (file)
@@ -11,6 +11,7 @@ import com.intellij.openapi.util.Ref;
 import com.intellij.packaging.artifacts.Artifact;
 import com.intellij.packaging.elements.PackagingElementFactory;
 import com.intellij.util.PathUtil;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -79,7 +80,7 @@ public abstract class ArtifactEditorTestCase extends PackagingElementsTestCase {
     final Ref<Boolean> dialogShown = Ref.create(false);
     final TestDialog oldDialog = Messages.setTestDialog(new TestDialog() {
       @Override
-      public int show(String message) {
+      public int show(@NotNull String message) {
         dialogShown.set(true);
         return 0;
       }
index 03a223ad20801c314f728a1d1ba3a54553936c92..8fffd0fcc2ef64c3d88353e3ff9c76735919ba3d 100644 (file)
@@ -2,6 +2,7 @@
 package com.intellij.debugger.actions;
 
 import com.intellij.debugger.SourcePosition;
+import com.intellij.debugger.engine.DebugProcessImpl;
 import com.intellij.debugger.engine.DebuggerUtils;
 import com.intellij.debugger.engine.SuspendContextImpl;
 import com.intellij.debugger.engine.evaluation.EvaluateException;
@@ -26,7 +27,10 @@ import com.intellij.psi.*;
 import com.intellij.util.DocumentUtil;
 import com.intellij.util.Range;
 import com.intellij.util.ThreeState;
+import com.intellij.util.containers.ContainerUtil;
 import com.sun.jdi.Location;
+import com.sun.jdi.Method;
+import com.sun.jdi.ReferenceType;
 import one.util.streamex.StreamEx;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -338,42 +342,67 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
       if (!targets.isEmpty()) {
         StackFrameProxyImpl frameProxy = suspendContext != null ? suspendContext.getFrameProxy() : null;
         if (frameProxy != null) {
+          // sanity check
           try {
-            Location location = frameProxy.location();
-            MethodBytecodeUtil.visit(location.method(), location.codeIndex(), new MethodVisitor(Opcodes.API_VERSION) {
-              boolean myLineMatch = false;
-
-              @Override
-              public void visitLineNumber(int line, Label start) {
-                myLineMatch = lines.isWithin(line - 1);
+            List<MethodSmartStepTarget> methodTargets =
+              StreamEx.of(targets)
+                .select(MethodSmartStepTarget.class)
+                .filter(target -> !target.needsBreakpointRequest())
+                .toList();
+            visitLinesMethods(frameProxy.location(), true, lines, (opcode, owner, name, desc, itf) -> {
+              if (name.startsWith("access$")) { // bridge method
+                ReferenceType cls = ContainerUtil.getFirstItem(frameProxy.getVirtualMachine().classesByName(owner));
+                if (cls != null) {
+                  Method method = DebuggerUtils.findMethod(cls, name, desc);
+                  if (method != null) {
+                    MethodBytecodeUtil.visit(method, new MethodVisitor(Opcodes.API_VERSION) {
+                      @Override
+                      public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
+                        if ("java/lang/AbstractMethodError".equals(owner)) {
+                          return;
+                        }
+                        removeMatchingMethod(methodTargets, owner, name, desc, suspendContext.getDebugProcess());
+                      }
+                    }, false);
+                  }
+                }
+              }
+              else {
+                removeMatchingMethod(methodTargets, owner, name, desc, suspendContext.getDebugProcess());
               }
+            });
+            if (!methodTargets.isEmpty()) {
+              return Collections.emptyList();
+            }
+          }
+          catch (Exception e) {
+            LOG.error(e);
+          }
 
-              @Override
-              public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
-                if (myLineMatch) {
-                  Iterator<SmartStepTarget> iterator = targets.iterator();
-                  while (iterator.hasNext()) {
-                    SmartStepTarget e = iterator.next();
-                    if (e instanceof MethodSmartStepTarget &&
-                        DebuggerUtilsEx.methodMatches(((MethodSmartStepTarget)e).getMethod(),
-                                                      owner.replace("/", "."), name, desc,
-                                                      suspendContext.getDebugProcess())) {
-                      iterator.remove();
-                      MethodSmartStepTarget target = (MethodSmartStepTarget)e;
-                      // fix ordinals
-                      existingMethodCalls(targets, target.getMethod())
-                        .forEach(t -> {
-                          int ordinal = t.getOrdinal();
-                          if (ordinal > target.getOrdinal()) {
-                            t.setOrdinal(ordinal - 1);
-                          }
-                        });
-                      break;
-                    }
-                  }
+          // remove already executed
+          try {
+            visitLinesMethods(frameProxy.location(), false, lines, (opcode, owner, name, desc, itf) -> {
+              Iterator<SmartStepTarget> iterator = targets.iterator();
+              while (iterator.hasNext()) {
+                SmartStepTarget e = iterator.next();
+                if (e instanceof MethodSmartStepTarget &&
+                    DebuggerUtilsEx.methodMatches(((MethodSmartStepTarget)e).getMethod(),
+                                                  owner.replace("/", "."), name, desc,
+                                                  suspendContext.getDebugProcess())) {
+                  iterator.remove();
+                  MethodSmartStepTarget target = (MethodSmartStepTarget)e;
+                  // fix ordinals
+                  existingMethodCalls(targets, target.getMethod())
+                    .forEach(t -> {
+                      int ordinal = t.getOrdinal();
+                      if (ordinal > target.getOrdinal()) {
+                        t.setOrdinal(ordinal - 1);
+                      }
+                    });
+                  break;
                 }
               }
-            }, true);
+            });
           }
           catch (Exception e) {
             LOG.info(e);
@@ -386,6 +415,42 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
     return Collections.emptyList();
   }
 
+  private static void removeMatchingMethod(List<MethodSmartStepTarget> targets,
+                                           String owner,
+                                           String name,
+                                           String desc,
+                                           DebugProcessImpl process) {
+    Iterator<MethodSmartStepTarget> iterator = targets.iterator();
+    while (iterator.hasNext()) {
+      if (DebuggerUtilsEx.methodMatches(iterator.next().getMethod(), owner.replace("/", "."), name, desc, process)) {
+        iterator.remove();
+        break;
+      }
+    }
+  }
+
+  private interface MethodInsnVisitor {
+    void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf);
+  }
+
+  private static void visitLinesMethods(Location location, boolean full, Range<Integer> lines, MethodInsnVisitor visitor) {
+    MethodBytecodeUtil.visit(location.method(), full ? Long.MAX_VALUE : location.codeIndex(), new MethodVisitor(Opcodes.API_VERSION) {
+      boolean myLineMatch = false;
+
+      @Override
+      public void visitLineNumber(int line, Label start) {
+        myLineMatch = lines.isWithin(line - 1);
+      }
+
+      @Override
+      public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
+        if (myLineMatch) {
+          visitor.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
+      }
+    }, true);
+  }
+
   private static StreamEx<MethodSmartStepTarget> existingMethodCalls(List<SmartStepTarget> targets, PsiMethod psiMethod) {
     return StreamEx.of(targets)
       .select(MethodSmartStepTarget.class)
index 8158d3d34cfe94751b29c2c435f8862371091618..ad96c0b44db2b7fd4ac585e7bbfda74c3c171ad3 100644 (file)
@@ -38,7 +38,7 @@ public class TestFilesIndex extends MapReduceIndex<Integer, Void, UsedSources> {
   @Nullable
   Collection<Integer> getTestDataFor(int testId) throws IOException {
     ForwardIndex forwardIndex = getForwardIndexMap();
-    KeyCollectionForwardIndexAccessor<Integer, Void> forwardIndexAccessor = (KeyCollectionForwardIndexAccessor<Integer, Void>)getForwardIndexAccessor();
+    KeyCollectionForwardIndexAccessor<Integer, Void, UsedSources> forwardIndexAccessor = (KeyCollectionForwardIndexAccessor<Integer, Void, UsedSources>)getForwardIndexAccessor();
     return forwardIndexAccessor.deserializeData(forwardIndex.get(testId));
   }
 
index 465798769829a8c5724636a3a006db0a8e0afccf..e0fefcf09d6e872977f619e1ee4c9021a97eccba 100644 (file)
@@ -29,11 +29,11 @@ import com.intellij.ui.components.JBList;
 import com.intellij.ui.popup.list.GroupedItemsListRenderer;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.ui.JBUI;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 
 import javax.swing.*;
-import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 import java.awt.*;
 import java.util.Collections;
@@ -55,7 +55,7 @@ public class ProjectTemplateList extends JPanel {
     add(myPanel, BorderLayout.CENTER);
 
     GroupedItemsListRenderer<ProjectTemplate> renderer = new GroupedItemsListRenderer<ProjectTemplate>(new ListItemDescriptorAdapter<ProjectTemplate>() {
-      @Nullable
+      @NotNull
       @Override
       public String getTextFor(ProjectTemplate value) {
         return value.getName();
@@ -80,12 +80,7 @@ public class ProjectTemplateList extends JPanel {
       }
     };
     myList.setCellRenderer(renderer);
-    myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
-      @Override
-      public void valueChanged(ListSelectionEvent e) {
-        updateSelection();
-      }
-    });
+    myList.getSelectionModel().addListSelectionListener(__ -> updateSelection());
 
     Messages.installHyperlinkSupport(myDescriptionPane);
   }
@@ -104,7 +99,7 @@ public class ProjectTemplateList extends JPanel {
     }
   }
 
-  public void setTemplates(List<ProjectTemplate> list, boolean preserveSelection) {
+  public void setTemplates(List<? extends ProjectTemplate> list, boolean preserveSelection) {
     Collections.sort(list, (o1, o2) -> Comparing.compare(o1 instanceof ArchivedProjectTemplate, o2 instanceof ArchivedProjectTemplate));
 
     int index = preserveSelection ? myList.getSelectedIndex() : -1;
@@ -142,13 +137,10 @@ public class ProjectTemplateList extends JPanel {
         myList.setSelectedValue(template, true);
       }
     }
-    myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
-      @Override
-      public void valueChanged(ListSelectionEvent e) {
-        ProjectTemplate template = getSelectedTemplate();
-        if (template != null) {
-          PropertiesComponent.getInstance().setValue(PROJECT_WIZARD_TEMPLATE, template.getName());
-        }
+    myList.getSelectionModel().addListSelectionListener(__ -> {
+      ProjectTemplate template = getSelectedTemplate();
+      if (template != null) {
+        PropertiesComponent.getInstance().setValue(PROJECT_WIZARD_TEMPLATE, template.getName());
       }
     });
   }
@@ -166,7 +158,7 @@ public class ProjectTemplateList extends JPanel {
   }
 
   @TestOnly
-  public boolean setSelectedTemplate(String name) {
+  boolean setSelectedTemplate(@NotNull String name) {
     ListModel model1 = myList.getModel();
     for (int j = 0; j < model1.getSize(); j++) {
       if (name.equals(((ProjectTemplate)model1.getElementAt(j)).getName())) {
index 5877220012375a0301ec90dff4caea8fa772dce4..b0a6de73fd35cb8814b157d062b29e5f42b5cc19 100644 (file)
@@ -54,8 +54,6 @@ import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 
 import javax.swing.*;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
 import java.awt.*;
 import java.net.URL;
 import java.util.HashMap;
@@ -70,9 +68,9 @@ import java.util.*;
 public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, Disposable {
   private static final Logger LOG = Logger.getInstance(ProjectTypeStep.class);
 
-  public static final Convertor<FrameworkSupportInModuleProvider,String> PROVIDER_STRING_CONVERTOR =
+  private static final Convertor<FrameworkSupportInModuleProvider,String> PROVIDER_STRING_CONVERTOR =
     o -> o.getId();
-  public static final Function<FrameworkSupportNode, String> NODE_STRING_FUNCTION = FrameworkSupportNodeBase::getId;
+  private static final Function<FrameworkSupportNode, String> NODE_STRING_FUNCTION = FrameworkSupportNodeBase::getId;
   private static final String TEMPLATES_CARD = "templates card";
   private static final String FRAMEWORKS_CARD = "frameworks card";
   private static final String PROJECT_WIZARD_GROUP = "project.wizard.group";
@@ -106,12 +104,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
 
     myProjectTypeList.setModel(new CollectionListModel<>(groups));
     myProjectTypeList.setSelectionModel(new SingleSelectionModel());
-    myProjectTypeList.addListSelectionListener(new ListSelectionListener() {
-      @Override
-      public void valueChanged(ListSelectionEvent e) {
-        updateSelection();
-      }
-    });
+    myProjectTypeList.addListSelectionListener(__ -> updateSelection());
     myProjectTypeList.setCellRenderer(new GroupedItemsListRenderer<TemplatesGroup>(new ListItemDescriptorAdapter<TemplatesGroup>() {
       @Nullable
       @Override
@@ -187,19 +180,9 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
       }
     };
 
-    myProjectTypeList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
-      @Override
-      public void valueChanged(ListSelectionEvent e) {
-        projectTypeChanged();
-      }
-    });
+    myProjectTypeList.getSelectionModel().addListSelectionListener(__ -> projectTypeChanged());
 
-    myTemplatesList.addListSelectionListener(new ListSelectionListener() {
-      @Override
-      public void valueChanged(ListSelectionEvent e) {
-        updateSelection();
-      }
-    });
+    myTemplatesList.addListSelectionListener(__ -> updateSelection());
 
     for (TemplatesGroup templatesGroup : myTemplatesMap.keySet()) {
       ModuleBuilder builder = templatesGroup.getModuleBuilder();
@@ -239,7 +222,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
     return ContainerUtil.intersects(Arrays.asList(roles), acceptable);
   }
 
-  public static MultiMap<TemplatesGroup, ProjectTemplate> getTemplatesMap(WizardContext context) {
+  private static MultiMap<TemplatesGroup, ProjectTemplate> getTemplatesMap(WizardContext context) {
     ProjectTemplatesFactory[] factories = ProjectTemplatesFactory.EP_NAME.getExtensions();
     final MultiMap<TemplatesGroup, ProjectTemplate> groups = new MultiMap<>();
     for (ProjectTemplatesFactory factory : factories) {
@@ -351,7 +334,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
   }
 
   // new TemplatesGroup selected
-  public void projectTypeChanged() {
+  private void projectTypeChanged() {
     TemplatesGroup group = getSelectedGroup();
     if (group == null || group == myLastSelectedGroup) return;
     myLastSelectedGroup = group;
@@ -431,7 +414,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
     showCard(TEMPLATES_CARD);
   }
 
-  private void setTemplatesList(TemplatesGroup group, Collection<ProjectTemplate> templates, boolean preserveSelection) {
+  private void setTemplatesList(TemplatesGroup group, Collection<? extends ProjectTemplate> templates, boolean preserveSelection) {
     List<ProjectTemplate> list = new ArrayList<>(templates);
     ModuleBuilder moduleBuilder = group.getModuleBuilder();
     if (moduleBuilder != null && !(moduleBuilder instanceof TemplateModuleBuilder)) {
@@ -463,7 +446,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
   }
 
   @Nullable
-  public ProjectTemplate getSelectedTemplate() {
+  private ProjectTemplate getSelectedTemplate() {
     return myCurrentCard == TEMPLATES_CARD ? myTemplatesList.getSelectedTemplate() : null;
   }
 
index f6e38b3d0a9353d3047811e36deb34b4ddf17d98..f6e038178ef9c8657181bff09810906b13d4a4da 100644 (file)
@@ -77,14 +77,12 @@ public class UIRootConfigurationAccessor extends RootConfigurationAccessor {
   @Override
   @Nullable
   public String getProjectSdkName(final Project project) {
-    final String projectJdkName = ProjectRootManager.getInstance(project).getProjectSdkName();
     final Sdk projectJdk = getProjectSdk(project);
     if (projectJdk != null) {
       return projectJdk.getName();
     }
-    else {
-      final ProjectSdksModel projectJdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel();
-      return projectJdksModel.findSdk(projectJdkName) == null ? projectJdkName : null;
-    }
+    final String projectJdkName = ProjectRootManager.getInstance(project).getProjectSdkName();
+    final ProjectSdksModel projectJdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel();
+    return projectJdkName != null && projectJdksModel.findSdk(projectJdkName) == null ? projectJdkName : null;
   }
 }
index 95efcaacb7f4c823a78f1649fda1223668b87382..cf95264bd20b021a4f4c57f1c1be9119d89c6edc 100644 (file)
@@ -17,6 +17,7 @@ import com.intellij.util.NullableFunction;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.MultiMap;
 import com.intellij.util.io.HttpRequests;
+import org.intellij.lang.annotations.Language;
 import org.jdom.Element;
 import org.jdom.JDOMException;
 import org.jetbrains.annotations.NotNull;
@@ -74,7 +75,7 @@ public class RemoteTemplatesFactory extends ProjectTemplatesFactory {
 
   @NotNull
   @TestOnly
-  public static MultiMap<String, ArchivedProjectTemplate> createFromText(@NotNull String value) throws IOException, JDOMException {
+  public static MultiMap<String, ArchivedProjectTemplate> createFromText(@NotNull @Language("XML") String value) throws IOException, JDOMException {
     return create(JDOMUtil.load(value));
   }
 
index 74d08af7eae866d2a8ad5ce06012ba3bc548ae5c..a7a215254843b7b3861bb00010f631b8ddab3302 100644 (file)
@@ -19,24 +19,25 @@ import com.intellij.util.containers.MultiMap;
  */
 public class RemoteTemplatesTest extends NewProjectWizardTestCase {
   public void testParsing() throws Exception {
-    MultiMap<String, ArchivedProjectTemplate> map = RemoteTemplatesFactory.createFromText("<templates>\n" +
-                                                                                  "  <template>\n" +
-                                                                                  "    <name>Facelets Demo</name>\n" +
-                                                                                  "    <description><![CDATA[\n" +
-                                                                                  "    Demonstrates IDEA support for Facelets technology\n" +
-                                                                                  "    ]]>\n" +
-                                                                                  "    </description>\n" +
-                                                                                  "    <path>facelets.zip</path>\n" +
-                                                                                  "    <moduleType>JAVA_MODULE</moduleType>\n" +
-                                                                                  "  </template>\n" +
-                                                                                  "  <template>\n" +
-                                                                                  "    <name>Incompatible</name>\n" +
-                                                                                  "    <description>Incompatible</description>\n" +
-                                                                                  "    <path>incompatible.zip</path>\n" +
-                                                                                  "    <moduleType>JAVA_MODULE</moduleType>\n" +
-                                                                                  "    <requiredPlugin>unknown.plugin</requiredPlugin>\n" +
-                                                                                  "  </template>\n" +
-                                                                                  "</templates>");
+    MultiMap<String, ArchivedProjectTemplate> map = RemoteTemplatesFactory.createFromText(
+      "<templates>\n" +
+      "  <template>\n" +
+      "    <name>Facelets Demo</name>\n" +
+      "    <description><![CDATA[\n" +
+      "    Demonstrates IDEA support for Facelets technology\n" +
+      "    ]]>\n" +
+      "    </description>\n" +
+      "    <path>facelets.zip</path>\n" +
+      "    <moduleType>JAVA_MODULE</moduleType>\n" +
+      "  </template>\n" +
+      "  <template>\n" +
+      "    <name>Incompatible</name>\n" +
+      "    <description>Incompatible</description>\n" +
+      "    <path>incompatible.zip</path>\n" +
+      "    <moduleType>JAVA_MODULE</moduleType>\n" +
+      "    <requiredPlugin>unknown.plugin</requiredPlugin>\n" +
+      "  </template>\n" +
+      "</templates>");
     assertEquals(1, map.size());
 
     ProjectTemplate facelets = map.values().iterator().next();
index f5d1902c52d19bb77f35850a873e49b8178f1fcb..e407ca42b7e5c5a172c1b16486a94d099ef76e80 100644 (file)
@@ -65,7 +65,7 @@ public class AnnotateMethodFix implements LocalQuickFix {
 
   @Override
   public boolean startInWriteAction() {
-    return false;
+    return !annotateOverriddenMethods();
   }
 
   @Override
index 227bb2d1ddccfed3b771e4c94efa0c1009880f6b..30bc1a7eeff0bda72bbdc4555f12e77441863837 100644 (file)
@@ -93,6 +93,12 @@ public abstract class ContractReturnValue {
     return FAIL_VALUE;
   }
 
+  public boolean isSuperValueOf(ContractReturnValue value) {
+    if (value == this || this == ANY_VALUE) return true;
+    if (this == NOT_NULL_VALUE && value.isNotNull()) return true;
+    return false;
+  }
+
   static DfaValue merge(DfaValue defaultValue, DfaValue newValue, DfaMemoryState memState) {
     if (defaultValue == null || defaultValue == DfaUnknownValue.getInstance()) return newValue;
     if (newValue == null || newValue == DfaUnknownValue.getInstance()) return defaultValue;
index c896c5bfc981ba5f0abf76f22d2c1b67bbad1a94..ac9b3667d3c5c0b22399dfb824e7f5e1376c072f 100644 (file)
@@ -7,8 +7,11 @@ import com.intellij.codeInspection.dataFlow.instructions.Instruction;
 import com.intellij.codeInspection.dataFlow.value.*;
 import com.intellij.codeInspection.dataFlow.value.DfaRelationValue.RelationType;
 import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiExpression;
+import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.ObjectUtils;
+import com.siyeh.ig.psiutils.ExpressionUtils;
 import one.util.streamex.EntryStream;
 import one.util.streamex.StreamEx;
 import org.jetbrains.annotations.Contract;
@@ -244,6 +247,20 @@ public class TrackingDfaMemoryState extends DfaMemoryStateImpl {
       return findChange(change -> change.getExpression() == expression, false);
     }
 
+    @Contract("null -> null")
+    @Nullable
+    MemoryStateChange findSubExpressionPush(@Nullable PsiExpression expression) {
+      if (expression == null) return null;
+      PsiElement topElement = ExpressionUtils.getPassThroughParent(expression);
+      return findChange(change -> {
+        PsiExpression changeExpression = change.getExpression();
+        if (changeExpression == null) return false;
+        return changeExpression == expression ||
+               (PsiTreeUtil.isAncestor(expression, changeExpression, true) &&
+                ExpressionUtils.getPassThroughParent(changeExpression) == topElement);
+      }, false);
+    }
+
     MemoryStateChange findRelation(DfaVariableValue value, @NotNull Predicate<Relation> relationPredicate, boolean startFromSelf) {
       return findChange(change -> {
         Change varChange = change.myChanges.get(value);
index e83126b62b61d0966bcfb9d9754b3de111fe77d1..8c40c0e70df6747eb6401df8cbf74e4b68559d63 100644 (file)
@@ -9,6 +9,7 @@ import com.intellij.codeInspection.dataFlow.instructions.*;
 import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet;
 import com.intellij.codeInspection.dataFlow.value.*;
 import com.intellij.codeInspection.dataFlow.value.DfaRelationValue.RelationType;
+import com.intellij.lang.ASTNode;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.util.Pair;
@@ -16,6 +17,8 @@ import com.intellij.openapi.util.Segment;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
+import com.intellij.psi.impl.source.tree.ChildRole;
+import com.intellij.psi.impl.source.tree.CompositeElement;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.ArrayUtil;
@@ -24,6 +27,7 @@ import com.intellij.util.containers.ContainerUtil;
 import com.siyeh.ig.psiutils.BoolUtils;
 import com.siyeh.ig.psiutils.ExpressionUtils;
 import one.util.streamex.StreamEx;
+import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -333,9 +337,10 @@ public class TrackingRunner extends StandardDataFlowRunner {
             Warning caused by narrowing conversion
             Warning caused by unary minus
             Warning caused by final field initializer
-  TODO: 3. Check how it works with 
+            Literal is not-null
+  TODO: 3. Check how it works with:
             Inliners (notably: Stream API)
-            Ternary operators
+            Boxed numbers
   TODO: 4. Check for possible performance disasters (likely on some code patterns current algo might blow up)
   TODO: 5. Problem when interesting state doesn't reach the current condition, need to do something with this    
    */
@@ -370,8 +375,8 @@ public class TrackingRunner extends StandardDataFlowRunner {
         Instruction instruction = change.myInstruction;
         if (instruction instanceof AssignInstruction && change.myTopOfStack == value) {
           PsiExpression rValue = ((AssignInstruction)instruction).getRExpression();
-          CauseItem item = new CauseItem("'" + value + "' was assigned", rValue);
-          MemoryStateChange push = change.findExpressionPush(rValue);
+          CauseItem item = createAssignmentCause((AssignInstruction)instruction, value);
+          MemoryStateChange push = change.findSubExpressionPush(rValue);
           if (push != null) {
             item.addChildren(findConstantValueCause(rValue, push, expectedValue));
           }
@@ -385,6 +390,34 @@ public class TrackingRunner extends StandardDataFlowRunner {
     return new CauseItem[0];
   }
 
+  @NotNull
+  @Contract("_, _ -> new")
+  private static CauseItem createAssignmentCause(AssignInstruction instruction, DfaValue target) {
+    PsiExpression rExpression = instruction.getRExpression();
+    PsiElement anchor = null;
+    if (rExpression != null) {
+      PsiElement parent = PsiUtil.skipParenthesizedExprUp(rExpression.getParent());
+      if (parent instanceof PsiAssignmentExpression) {
+        anchor = ((PsiAssignmentExpression)parent).getOperationSign();
+      }
+      else if (parent instanceof PsiVariable) {
+        ASTNode node = parent.getNode();
+        if (node instanceof CompositeElement) {
+          anchor = ((CompositeElement)node).findChildByRoleAsPsiElement(ChildRole.INITIALIZER_EQ);
+        }
+      }
+      if (anchor == null) {
+        anchor = rExpression;
+      }
+    }
+    PsiExpression stripped = PsiUtil.skipParenthesizedExprDown(rExpression);
+    String suffix = "";
+    if (stripped instanceof PsiLiteralExpression) {
+      suffix = " to '" + StringUtil.shortenTextWithEllipsis(stripped.getText(), 40, 5) + "'";
+    }
+    return new CauseItem("'" + target + "' was assigned" + suffix, anchor);
+  }
+
   private static CauseItem[] findBooleanResultCauses(PsiExpression expression,
                                                      MemoryStateChange history,
                                                      boolean value) {
@@ -509,6 +542,24 @@ public class TrackingRunner extends StandardDataFlowRunner {
     ProgressManager.checkCanceled();
     DfaValue leftValue = leftChange.myTopOfStack;
     DfaValue rightValue = rightChange.myTopOfStack;
+    Pair<MemoryStateChange, DfaNullability> leftNullability = leftChange.findFact(leftValue, DfaFactType.NULLABILITY);
+    Pair<MemoryStateChange, DfaNullability> rightNullability = rightChange.findFact(rightValue, DfaFactType.NULLABILITY);
+    if ((leftNullability.second == DfaNullability.NULL && rightNullability.second == DfaNullability.NOT_NULL) ||
+        (rightNullability.second == DfaNullability.NULL && leftNullability.second == DfaNullability.NOT_NULL)) {
+      return new CauseItem[]{findNullabilityCause(leftChange, leftNullability.first, leftNullability.second),
+        findNullabilityCause(rightChange, rightNullability.first, rightNullability.second)};
+    }
+
+    Pair<MemoryStateChange, LongRangeSet> leftRange = leftChange.findFact(leftValue, DfaFactType.RANGE);
+    Pair<MemoryStateChange, LongRangeSet> rightRange = rightChange.findFact(rightValue, DfaFactType.RANGE);
+    if (leftRange.second != null && rightRange.second != null) {
+      LongRangeSet fromRelation = rightRange.second.fromRelation(relationType.getNegated());
+      if (fromRelation != null && !fromRelation.intersects(leftRange.second)) {
+        return new CauseItem[]{
+          findRangeCause(leftChange, leftRange.first, leftRange.second, "left operand is %s"),
+          findRangeCause(rightChange, rightRange.first, rightRange.second, "right operand is %s")};
+      }
+    }
     if (leftValue instanceof DfaVariableValue) {
       Relation relation = new Relation(relationType, rightValue);
       MemoryStateChange change = findRelationAddedChange(leftChange, (DfaVariableValue)leftValue, relation);
@@ -538,24 +589,6 @@ public class TrackingRunner extends StandardDataFlowRunner {
         return new CauseItem[]{findRelationCause(change, (DfaVariableValue)rightValue, relation, leftChange)};
       }
     }
-    Pair<MemoryStateChange, DfaNullability> leftNullability = leftChange.findFact(leftValue, DfaFactType.NULLABILITY);
-    Pair<MemoryStateChange, DfaNullability> rightNullability = rightChange.findFact(rightValue, DfaFactType.NULLABILITY);
-    if ((leftNullability.second == DfaNullability.NULL && rightNullability.second == DfaNullability.NOT_NULL) ||
-        (rightNullability.second == DfaNullability.NULL && leftNullability.second == DfaNullability.NOT_NULL)) {
-      return new CauseItem[]{findNullabilityCause(leftChange, leftNullability.first, leftNullability.second),
-        findNullabilityCause(rightChange, rightNullability.first, rightNullability.second)};
-    }
-
-    Pair<MemoryStateChange, LongRangeSet> leftRange = leftChange.findFact(leftValue, DfaFactType.RANGE);
-    Pair<MemoryStateChange, LongRangeSet> rightRange = rightChange.findFact(rightValue, DfaFactType.RANGE);
-    if (leftRange.second != null && rightRange.second != null) {
-      LongRangeSet fromRelation = rightRange.second.fromRelation(relationType.getNegated());
-      if (fromRelation != null && !fromRelation.intersects(leftRange.second)) {
-        return new CauseItem[]{
-          findRangeCause(leftChange, leftRange.first, leftRange.second, "left operand is %s"),
-          findRangeCause(rightChange, rightRange.first, rightRange.second, "right operand is %s")};
-      }
-    }
     return new CauseItem[0];
   }
 
@@ -564,31 +597,19 @@ public class TrackingRunner extends StandardDataFlowRunner {
                                              Relation relation, MemoryStateChange counterPartChange) {
     Instruction instruction = change.myInstruction;
     String condition = value + " " + relation;
-    if (relation.myCounterpart instanceof DfaConstValue &&
-        ((DfaConstValue)relation.myCounterpart).getValue() == null && relation.myRelationType == RelationType.NE) {
-      if (instruction instanceof CheckNotNullInstruction) {
-        PsiExpression expression = ((CheckNotNullInstruction)instruction).getProblem().getDereferencedExpression();
-        String text = expression == null ? value.toString() : expression.getText();
-        return new CauseItem("'" + text + "' was dereferenced", expression);
-      }
-      if (instruction instanceof InstanceofInstruction) {
-        PsiExpression expression = ((InstanceofInstruction)instruction).getExpression();
-        return new CauseItem("the 'instanceof' check implies non-nullity", expression);
-      }
-    }
     if (instruction instanceof AssignInstruction) {
       DfaValue target = change.myTopOfStack;
-      PsiExpression rValue = PsiUtil.skipParenthesizedExprDown(((AssignInstruction)instruction).getRExpression());
+      PsiExpression rValue = ((AssignInstruction)instruction).getRExpression();
+      CauseItem item = createAssignmentCause((AssignInstruction)instruction, target);
       if (target == value) {
-        CauseItem item = new CauseItem("'" + target + "' was assigned", rValue);
-        MemoryStateChange rValuePush = change.findExpressionPush(rValue);
+        MemoryStateChange rValuePush = change.findSubExpressionPush(rValue);
         if (rValuePush != null) {
           item.addChildren(findRelationCause(relation.myRelationType, rValuePush, counterPartChange));
         }
         return item;
       }
       if (target == relation.myCounterpart) {
-        return new CauseItem("'" + target + "' was assigned", rValue);
+        return item;
       }
     }
     PsiExpression expression = change.getExpression();
@@ -614,43 +635,36 @@ public class TrackingRunner extends StandardDataFlowRunner {
 
   private static CauseItem findNullabilityCause(MemoryStateChange factUse, MemoryStateChange factDef, DfaNullability nullability) {
     PsiExpression expression = factUse.getExpression();
-    if (factDef != null && expression != null) {
-      DfaValue value = factUse.myTopOfStack;
-      if (factDef.myInstruction instanceof AssignInstruction && factDef.myTopOfStack == value) {
-        PsiExpression rExpression = PsiUtil.skipParenthesizedExprDown(((AssignInstruction)factDef.myInstruction).getRExpression());
-        while (rExpression instanceof PsiTypeCastExpression) {
-          rExpression = PsiUtil.skipParenthesizedExprDown(((PsiTypeCastExpression)rExpression).getOperand());
-        }
-        if (rExpression != null) {
-          MemoryStateChange rValuePush = factDef.findExpressionPush(rExpression);
-          if (rValuePush != null) {
-            CauseItem assignmentItem = new CauseItem("'" + value + "' was assigned", rExpression);
-            Pair<MemoryStateChange, DfaNullability> rValueFact = rValuePush.findFact(rValuePush.myTopOfStack, DfaFactType.NULLABILITY);
-            assignmentItem.addChildren(findNullabilityCause(rValuePush, rValueFact.first, nullability));
-            return assignmentItem;
-          }
-        }
-      }
-      PsiExpression defExpression = factDef.getExpression();
-      if (defExpression != null) {
-        return new CauseItem("'" + expression.getText() + "' is known to be '" + nullability.getPresentationName() + "' from #ref", defExpression);
+    if (expression instanceof PsiTypeCastExpression) {
+      MemoryStateChange operandPush = factUse.findSubExpressionPush(((PsiTypeCastExpression)expression).getOperand());
+      if (operandPush != null) {
+        return findNullabilityCause(operandPush, factDef, nullability);
       }
     }
     if (expression instanceof PsiMethodCallExpression) {
       PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
       PsiMethod method = call.resolveMethod();
-      return fromMemberNullability(nullability, method, "method", call.getMethodExpression().getReferenceNameElement());
+      CauseItem causeItem = fromMemberNullability(nullability, method, "method", call.getMethodExpression().getReferenceNameElement());
+      if (causeItem != null) return causeItem;
+      switch (nullability) {
+        case NULL:
+        case NULLABLE:
+          return fromCallContract(factUse, call, ContractReturnValue.returnNull());
+        case NOT_NULL:
+          return fromCallContract(factUse, call, ContractReturnValue.returnNotNull());
+        default:
+      }
     }
     if (expression instanceof PsiReferenceExpression) {
       PsiVariable variable = ObjectUtils.tryCast(((PsiReferenceExpression)expression).resolve(), PsiVariable.class);
-      if (variable instanceof PsiField) {
-        return fromMemberNullability(nullability, variable, "field", ((PsiReferenceExpression)expression).getReferenceNameElement());
-      }
-      if (variable instanceof PsiParameter) {
-        return fromMemberNullability(nullability, variable, "parameter", ((PsiReferenceExpression)expression).getReferenceNameElement());
-      }
       if (variable != null) {
-        return fromMemberNullability(nullability, variable, "variable", ((PsiReferenceExpression)expression).getReferenceNameElement());
+        String memberTitle = variable instanceof PsiField ? "field" :
+                             variable instanceof PsiParameter ? "parameter" :
+                             "variable";
+        CauseItem causeItem = fromMemberNullability(nullability, variable, memberTitle, expression);
+        if (causeItem != null) {
+          return causeItem;
+        }
       }
     }
     if (nullability == DfaNullability.NOT_NULL) {
@@ -658,6 +672,37 @@ public class TrackingRunner extends StandardDataFlowRunner {
       if (explanation != null) {
         return new CauseItem("expression cannot be null as it's " + explanation, expression);
       }
+      if (factDef != null) {
+        if (factDef.myInstruction instanceof CheckNotNullInstruction) {
+          PsiExpression dereferenced = ((CheckNotNullInstruction)factDef.myInstruction).getProblem().getDereferencedExpression();
+          String text = dereferenced == null ? factUse.myTopOfStack.toString() : dereferenced.getText();
+          return new CauseItem("'" + text + "' was dereferenced", dereferenced);
+        }
+        if (factDef.myInstruction instanceof InstanceofInstruction) {
+          PsiExpression operand = ((InstanceofInstruction)factDef.myInstruction).getExpression();
+          return new CauseItem("the 'instanceof' check implies non-nullity", operand);
+        }
+      }
+    }
+    if (factDef != null && expression != null) {
+      DfaValue value = factUse.myTopOfStack;
+      if (factDef.myInstruction instanceof AssignInstruction && factDef.myTopOfStack == value) {
+        PsiExpression rExpression = ((AssignInstruction)factDef.myInstruction).getRExpression();
+        if (rExpression != null) {
+          MemoryStateChange rValuePush = factDef.findSubExpressionPush(rExpression);
+          if (rValuePush != null) {
+            CauseItem assignmentItem = createAssignmentCause((AssignInstruction)factDef.myInstruction, value);
+            Pair<MemoryStateChange, DfaNullability> rValueFact = rValuePush.findFact(rValuePush.myTopOfStack, DfaFactType.NULLABILITY);
+            assignmentItem.addChildren(findNullabilityCause(rValuePush, rValueFact.first, nullability));
+            return assignmentItem;
+          }
+        }
+      }
+      PsiExpression defExpression = factDef.getExpression();
+      if (defExpression != null) {
+        return new CauseItem("'" + expression.getText() + "' is known to be '" + nullability.getPresentationName() + "' from #ref",
+                             defExpression);
+      }
     }
     return null;
   }
@@ -671,6 +716,12 @@ public class TrackingRunner extends StandardDataFlowRunner {
         String message;
         String name = ((PsiNamedElement)owner).getName();
         if (info.isInferred()) {
+          if (owner instanceof PsiParameter &&
+              anchor instanceof PsiReferenceExpression &&
+              ((PsiReferenceExpression)anchor).isReferenceTo(owner)) {
+            // Do not use inference inside method itself
+            return null;
+          }
           message = memberName + " '" + name + "' was inferred to be '" + nullability.getPresentationName() + "'";
         }
         else if (info.isExternal()) {
@@ -715,6 +766,27 @@ public class TrackingRunner extends StandardDataFlowRunner {
     return null;
   }
 
+  private static CauseItem fromCallContract(MemoryStateChange history, PsiCallExpression call, ContractReturnValue contractReturnValue) {
+    PsiMethod method = call.resolveMethod();
+    if (method == null) return null;
+    List<? extends MethodContract> contracts =
+      ContainerUtil.filter(JavaMethodContractUtil.getMethodCallContracts(method, call),
+                           mc -> contractReturnValue.isSuperValueOf(mc.getReturnValue()));
+    boolean explicit = JavaMethodContractUtil.hasExplicitContractAnnotation(method);
+    if (call instanceof PsiMethodCallExpression) {
+      PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)call).getMethodExpression();
+      String name = methodExpression.getReferenceName();
+      for (MethodContract contract : contracts) {
+        if (contract.isTrivial()) {
+          return new CauseItem("according to " + (explicit ? "contract" : "inferred contract") +
+                               ", method '" + name + "' always returns '" + contract.getReturnValue() + "' value",
+                               methodExpression.getReferenceNameElement());
+        }
+      }
+    }
+    return null;
+  }
+
   private static CauseItem findRangeCause(MemoryStateChange factUse,
                                           MemoryStateChange factDef,
                                           LongRangeSet range,
@@ -791,11 +863,11 @@ public class TrackingRunner extends StandardDataFlowRunner {
     CauseItem item = new CauseItem(String.format(template, rangeText), factUse);
     if (factDef != null) {
       if (factDef.myInstruction instanceof AssignInstruction && factDef.myTopOfStack == value) {
-        PsiExpression rExpression = PsiUtil.skipParenthesizedExprDown(((AssignInstruction)factDef.myInstruction).getRExpression());
+        PsiExpression rExpression = ((AssignInstruction)factDef.myInstruction).getRExpression();
         if (rExpression != null) {
-          MemoryStateChange rValuePush = factDef.findExpressionPush(rExpression);
+          MemoryStateChange rValuePush = factDef.findSubExpressionPush(rExpression);
           if (rValuePush != null) {
-            CauseItem assignmentItem = new CauseItem("'" + value + "' was assigned", rExpression);
+            CauseItem assignmentItem = createAssignmentCause((AssignInstruction)factDef.myInstruction, value);
             Pair<MemoryStateChange, LongRangeSet> rValueFact = rValuePush.findFact(rValuePush.myTopOfStack, DfaFactType.RANGE);
             assignmentItem.addChildren(findRangeCause(rValuePush, rValueFact.first, range, "Value is %s"));
             item.addChildren(assignmentItem);
index f8c6df99fa65094a304b212c53e94d588f6a529e..e4245aedb290bcb863e56cdf05fc63a5943144d6 100644 (file)
@@ -550,21 +550,19 @@ public class RefJavaManagerImpl extends RefJavaManager {
     //TODO support suppressions by comment tag in kotlin
     private void processComments(@NotNull UElement node) {
       for (UComment comment : node.getComments()) {
-        if (comment instanceof UComment) {
-          PsiElement psi = comment.getSourcePsi();
-          if (psi instanceof PsiDocComment) {
-            final PsiDocTag[] tags = ((PsiDocComment)psi).getTags();
-            for (PsiDocTag tag : tags) {
-              if (Comparing.strEqual(tag.getName(), SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME)) {
-                final PsiElement[] dataElements = tag.getDataElements();
-                if (dataElements.length > 0) {
-                  final PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(psi, PsiModifierListOwner.class);
-                  if (listOwner != null) {
-                    final WritableRefElement element = (WritableRefElement)myRefManager.getReference(listOwner);
-                    if (element != null) {
-                      String suppression = StringUtil.join(dataElements, PsiElement::getText, ",");
-                      element.addSuppression(suppression);
-                    }
+        PsiElement psi = comment.getSourcePsi();
+        if (psi instanceof PsiDocComment) {
+          final PsiDocTag[] tags = ((PsiDocComment)psi).getTags();
+          for (PsiDocTag tag : tags) {
+            if (Comparing.strEqual(tag.getName(), SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME)) {
+              final PsiElement[] dataElements = tag.getDataElements();
+              if (dataElements.length > 0) {
+                final PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(psi, PsiModifierListOwner.class);
+                if (listOwner != null) {
+                  final WritableRefElement element = (WritableRefElement)myRefManager.getReference(listOwner);
+                  if (element != null) {
+                    String suppression = StringUtil.join(dataElements, PsiElement::getText, ",");
+                    element.addSuppression(suppression);
                   }
                 }
               }
index fb174641a1a21b7351b5d95a07c40236e376b5de..52441e8ae87a20f96b9160ec69b7a47b66ca2f27 100644 (file)
                      groupKey="group.names.verbose.or.redundant.code.constructs" enabledByDefault="true" level="INFORMATION"
                      implementationClass="com.intellij.codeInspection.ExplicitArrayFillingInspection"
                      displayName="Explicit array filling"/>
+    <localInspection groupPath="Java" language="JAVA" shortName="ExplicitMinMaxCheck"
+                     groupBundle="messages.InspectionsBundle"
+                     groupKey="group.names.verbose.or.redundant.code.constructs" enabledByDefault="true" level="WARNING"
+                     implementationClass="com.intellij.codeInspection.ExplicitMinMaxCheckInspection"
+                     displayName="Explicit min/max check"/>
     <localInspection groupPath="Java" language="JAVA" shortName="CollectionAddAllCanBeReplacedWithConstructor"
                      groupBundle="messages.InspectionsBundle"
                      groupKey="group.names.performance.issues" enabledByDefault="true" level="WARNING"
index 0096c12ebe6e4de6b227bcfeddc53e4d0786d56c..807c25dc7ea8de3782489e76131ca912d7deb73d 100644 (file)
@@ -240,8 +240,10 @@ public class NullableNotNullManagerImpl extends NullableNotNullManager implement
       if (container instanceof PsiPackage) {
         PsiFile file = annotation.getContainingFile();
         ProjectFileIndex index = ProjectRootManager.getInstance(file.getProject()).getFileIndex();
-        VirtualFile annotationRoot = index.getClassRootForFile(file.getVirtualFile());
-        VirtualFile ownerRoot = index.getClassRootForFile(owner.getContainingFile().getVirtualFile());
+        VirtualFile annotationFile = file.getVirtualFile();
+        VirtualFile annotationRoot = annotationFile == null ? null : index.getClassRootForFile(annotationFile);
+        VirtualFile ownerFile = owner.getContainingFile().getVirtualFile();
+        VirtualFile ownerRoot = ownerFile == null ? null : index.getClassRootForFile(ownerFile);
         if (ownerRoot != null && !ownerRoot.equals(annotationRoot)) {
           continue;
         }
diff --git a/java/java-impl/src/com/intellij/codeInspection/ExplicitMinMaxCheckInspection.java b/java/java-impl/src/com/intellij/codeInspection/ExplicitMinMaxCheckInspection.java
new file mode 100644 (file)
index 0000000..ec0f8a2
--- /dev/null
@@ -0,0 +1,183 @@
+// 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.codeInspection.ui.MultipleCheckboxOptionsPanel;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.TypeConversionUtil;
+import com.siyeh.ig.PsiReplacementUtil;
+import com.siyeh.ig.psiutils.CommentTracker;
+import com.siyeh.ig.psiutils.ControlFlowUtils;
+import com.siyeh.ig.psiutils.EquivalenceChecker;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+import static com.intellij.util.ObjectUtils.tryCast;
+
+public class ExplicitMinMaxCheckInspection extends AbstractBaseJavaLocalInspectionTool {
+
+  public boolean disableForNonIntegralTypes = false;
+
+  @Nullable
+  @Override
+  public JComponent createOptionsPanel() {
+    MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
+    panel.addCheckbox(InspectionsBundle.message("inspection.explicit.min.max.check.disable.for.non.integral"),
+                      "disableForNonIntegralTypes");
+    return panel;
+  }
+
+  @NotNull
+  @Override
+  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
+    return new JavaElementVisitor() {
+
+      @Override
+      public void visitIfStatement(PsiIfStatement statement) {
+        PsiBinaryExpression condition = getCondition(statement.getCondition());
+        if (condition == null) return;
+        PsiStatement thenStatement = ControlFlowUtils.stripBraces(statement.getThenBranch());
+        if (thenStatement == null) return;
+        PsiStatement elseStatement = ControlFlowUtils.stripBraces(statement.getElseBranch());
+        if (elseStatement == null) return;
+        if (thenStatement.getClass() != elseStatement.getClass()) return;
+
+        PsiExpression thenExpression = getBranchExpression(thenStatement);
+        if (thenExpression == null) return;
+        PsiExpression elseExpression = getBranchExpression(elseStatement);
+        if (elseExpression == null) return;
+        if (thenExpression instanceof PsiAssignmentExpression && elseExpression instanceof PsiAssignmentExpression) {
+          PsiAssignmentExpression thenAssignment = (PsiAssignmentExpression)thenExpression;
+          PsiAssignmentExpression elseAssignment = (PsiAssignmentExpression)elseExpression;
+          if (!thenAssignment.getOperationTokenType().equals(elseAssignment.getOperationTokenType())) return;
+          EquivalenceChecker equivalenceChecker = EquivalenceChecker.getCanonicalPsiEquivalence();
+          if (!equivalenceChecker.expressionsAreEquivalent(thenAssignment.getLExpression(), elseAssignment.getLExpression())) return;
+          visitConditional(statement.getFirstChild(), condition, thenAssignment.getRExpression(), elseAssignment.getRExpression());
+        }
+        else {
+          visitConditional(statement.getFirstChild(), condition, thenExpression, elseExpression);
+        }
+      }
+
+      @Override
+      public void visitConditionalExpression(PsiConditionalExpression expression) {
+        PsiBinaryExpression condition = getCondition(expression.getCondition());
+        if (condition == null) return;
+        visitConditional(expression, condition, expression.getThenExpression(), expression.getElseExpression());
+      }
+
+      private void visitConditional(@NotNull PsiElement element,
+                                    @NotNull PsiBinaryExpression condition,
+                                    @Nullable PsiExpression thenExpression,
+                                    @Nullable PsiExpression elseExpression) {
+        if (thenExpression == null || elseExpression == null) return;
+        PsiExpression left = condition.getLOperand();
+        PsiExpression right = condition.getROperand();
+        if (right == null) return;
+        if (!hasCompatibleType(left) || !hasCompatibleType(right) ||
+            PsiUtil.isIncrementDecrementOperation(left) || PsiUtil.isIncrementDecrementOperation(right)) {
+          return;
+        }
+        EquivalenceChecker equivalenceChecker = EquivalenceChecker.getCanonicalPsiEquivalence();
+        boolean useMathMin = equivalenceChecker.expressionsAreEquivalent(left, elseExpression);
+        if (!useMathMin && !equivalenceChecker.expressionsAreEquivalent(left, thenExpression)) return;
+        if (!equivalenceChecker.expressionsAreEquivalent(right, useMathMin ? thenExpression : elseExpression)) return;
+        useMathMin ^= JavaTokenType.LT.equals(condition.getOperationTokenType());
+        holder.registerProblem(element,
+                               InspectionsBundle.message("inspection.explicit.min.max.check.description", useMathMin ? "min" : "max"),
+                               new ReplaceWithMinMaxFix(useMathMin));
+      }
+
+      private boolean hasCompatibleType(@NotNull PsiExpression expression) {
+        PsiType type = expression.getType();
+        if (type == null) return false;
+        int rank = TypeConversionUtil.getTypeRank(type);
+        if (rank < TypeConversionUtil.INT_RANK || rank > TypeConversionUtil.DOUBLE_RANK) return false;
+        return !disableForNonIntegralTypes || rank <= TypeConversionUtil.LONG_RANK;
+      }
+    };
+  }
+
+  @Nullable
+  private static PsiBinaryExpression getCondition(@Nullable PsiExpression expression) {
+    PsiBinaryExpression condition = tryCast(ParenthesesUtils.stripParentheses(expression), PsiBinaryExpression.class);
+    if (condition == null) return null;
+    IElementType tokenType = condition.getOperationTokenType();
+    return JavaTokenType.LT.equals(tokenType) || JavaTokenType.GT.equals(tokenType) ? condition : null;
+  }
+
+  @Nullable
+  private static PsiExpression getBranchExpression(@NotNull PsiStatement statement) {
+    if (statement instanceof PsiReturnStatement) {
+      return ((PsiReturnStatement)statement).getReturnValue();
+    }
+    else if (statement instanceof PsiBreakStatement) {
+      return ((PsiBreakStatement)statement).getExpression();
+    }
+    else if (statement instanceof PsiExpressionStatement) {
+      return PsiTreeUtil.findChildOfType(((PsiExpressionStatement)statement).getExpression(), PsiAssignmentExpression.class, false);
+    }
+    return null;
+  }
+
+  private static class ReplaceWithMinMaxFix implements LocalQuickFix {
+
+    private final boolean myUseMathMin;
+
+    @Contract(pure = true)
+    private ReplaceWithMinMaxFix(boolean useMathMin) {
+      myUseMathMin = useMathMin;
+    }
+
+    @Nls(capitalization = Nls.Capitalization.Sentence)
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return CommonQuickFixBundle.message("fix.replace.with.x", "Math." + (myUseMathMin ? "min" : "max"));
+    }
+
+    @Override
+    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+      PsiElement element = descriptor.getPsiElement();
+      if (element instanceof PsiConditionalExpression) {
+        PsiBinaryExpression condition = getCondition(((PsiConditionalExpression)element).getCondition());
+        if (condition == null) return;
+        String replacement = createReplacement(condition);
+        if (replacement == null) return;
+        PsiReplacementUtil.replaceExpression((PsiExpression)element, replacement, new CommentTracker());
+        return;
+      }
+      PsiIfStatement ifStatement = PsiTreeUtil.getParentOfType(element, PsiIfStatement.class);
+      if (ifStatement == null) return;
+      PsiBinaryExpression condition = getCondition(ifStatement.getCondition());
+      if (condition == null) return;
+      String replacement = createReplacement(condition);
+      if (replacement == null) return;
+      PsiStatement thenBranch = ControlFlowUtils.stripBraces(ifStatement.getThenBranch());
+      if (thenBranch == null) return;
+      PsiExpression toReplace = getBranchExpression(thenBranch);
+      if (toReplace instanceof PsiAssignmentExpression) toReplace = ((PsiAssignmentExpression)toReplace).getRExpression();
+      if (toReplace == null) return;
+      PsiReplacementUtil.replaceExpression(toReplace, replacement, new CommentTracker());
+      CommentTracker tracker = new CommentTracker();
+      tracker.text(thenBranch);
+      PsiReplacementUtil.replaceStatement(ifStatement, thenBranch.getText(), tracker);
+    }
+
+    @Nullable
+    private String createReplacement(@NotNull PsiBinaryExpression condition) {
+      PsiExpression left = condition.getLOperand();
+      PsiExpression right = condition.getROperand();
+      if (right == null) return null;
+      return CommonClassNames.JAVA_LANG_MATH + (myUseMathMin ? ".min" : ".max") + "(" + left.getText() + "," + right.getText() + ")";
+    }
+  }
+}
index 332648d6cb9437587a77d1f9496f19ffdd63f019..c8a185c6e684d69a5ca775ab610eba95f85ca07b 100644 (file)
@@ -147,7 +147,7 @@ public class FindDfaProblemCauseFix implements LocalQuickFix, LowPriorityAction
           highlighter.getAndSet(null).dropHighlight();
         }
       })
-      .setItemChosenCallback(cause -> ReadAction.run(() -> navigate(editor, file, cause.myCauseItem)))
+      .setItemChosenCallback(cause -> navigate(editor, file, cause.myCauseItem))
       .createPopup();
     popup.showInBestPositionFor(editor);
   }
index 937a159d39df5c1bbed57076b2bf1ea709ada83d..d0e29c8b26ae9715028100d79a357894b94d7077 100644 (file)
@@ -20,7 +20,6 @@ import com.intellij.lang.java.JavaLanguage;
 import com.intellij.navigation.ChooseByNameContributorEx;
 import com.intellij.navigation.GotoClassContributor;
 import com.intellij.navigation.NavigationItem;
-import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiFile;
@@ -30,41 +29,15 @@ import com.intellij.psi.presentation.java.SymbolPresentationUtil;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.PsiShortNamesCache;
 import com.intellij.psi.util.ClassUtil;
-import com.intellij.util.ArrayUtil;
 import com.intellij.util.Processor;
-import com.intellij.util.Processors;
 import com.intellij.util.indexing.FindSymbolParameters;
 import com.intellij.util.indexing.IdFilter;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.regex.Matcher;
 
 public class DefaultClassNavigationContributor implements ChooseByNameContributorEx, GotoClassContributor {
-  @Override
-  @NotNull
-  public String[] getNames(Project project, boolean includeNonProjectItems) {
-    GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
-    List<String> result = new ArrayList<>();
-    Processor<String> processor = Processors.cancelableCollectProcessor(result);
-
-    processNames(processor, scope, IdFilter.getProjectIdFilter(project, includeNonProjectItems));
-
-    return ArrayUtil.toStringArray(result);
-  }
-
-  @Override
-  @NotNull
-  public NavigationItem[] getItemsByName(String name, final String pattern, Project project, boolean includeNonProjectItems) {
-    List<NavigationItem> result = new ArrayList<>();
-    Processor<NavigationItem> processor = Processors.cancelableCollectProcessor(result);
-    processElementsWithName(name, processor, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems));
-
-    return result.isEmpty() ? NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY :
-           result.toArray(NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY);
-  }
 
   @Override
   public String getQualifiedName(final NavigationItem item) {
index bba5b597d4b5870c5f316541ca4651ea0c41d455..e302d7363ed6153e0fc34ea6a43e52cb03cd164e 100644 (file)
@@ -30,51 +30,13 @@ import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.*;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Set;
 
 public class DefaultSymbolNavigationContributor implements ChooseByNameContributorEx, GotoClassContributor {
   private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.DefaultSymbolNavigationContributor");
 
-  @Override
-  @NotNull
-  public String[] getNames(Project project, boolean includeNonProjectItems) {
-    PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project);
-    Set<String> set = new HashSet<>();
-    Collections.addAll(set, cache.getAllMethodNames());
-    Collections.addAll(set, cache.getAllFieldNames());
-    Collections.addAll(set, cache.getAllClassNames());
-    return ArrayUtil.toStringArray(set);
-  }
-
-  @Override
-  @NotNull
-  public NavigationItem[] getItemsByName(String name, final String pattern, Project project, boolean includeNonProjectItems) {
-    GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
-    PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project);
-
-    Condition<PsiMember> qualifiedMatcher = getQualifiedNameMatcher(pattern);
-
-    List<PsiMember> result = new ArrayList<>();
-    for (PsiMethod method : cache.getMethodsByName(name, scope)) {
-      if (!method.isConstructor() && isOpenable(method) && !hasSuperMethod(method, scope, qualifiedMatcher, pattern)) {
-        result.add(method);
-      }
-    }
-    for (PsiField field : cache.getFieldsByName(name, scope)) {
-      if (isOpenable(field)) {
-        result.add(field);
-      }
-    }
-    for (PsiClass aClass : cache.getClassesByName(name, scope)) {
-      if (isOpenable(aClass)) {
-        result.add(aClass);
-      }
-    }
-    PsiMember[] array = result.toArray(PsiMember.EMPTY_ARRAY);
-    Arrays.sort(array, MyComparator.INSTANCE);
-    return array;
-  }
-
   @Nullable
   @Override
   public String getQualifiedName(NavigationItem item) {
index 996b598b53c701ac7efdd6461fefb64dc98ad4cc..89e4119bd8b278f7576d328ca1102bedd21e1b9b 100644 (file)
@@ -29,7 +29,5 @@ internal class RangeExpression(
 
   override fun calculateQuickResult(context: ExpressionContext): Result? = calculateResult(context)
 
-  override fun requiresCommittedPSI(): Boolean = false
-
   override fun calculateLookupItems(context: ExpressionContext): Array<out LookupElement> = LookupElement.EMPTY_ARRAY
 }
index ff7e4f35079b03de7a18f90fd87a0cce9e9b89fb..27980dbe6d4d31cc612ebc64b2b2d8afd4d39e2d 100644 (file)
@@ -26,7 +26,7 @@ import com.intellij.refactoring.RefactoringActionHandler;
 import com.intellij.refactoring.inheritanceToDelegation.InheritanceToDelegationHandler;
 import org.jetbrains.annotations.NotNull;
 
-import static com.intellij.refactoring.actions.TurnRefsToSuperAction.isJavaClassHeader;
+import static com.intellij.refactoring.actions.RefactoringActionContextUtil.isJavaClassHeader;
 
 public class InheritanceToDelegationAction extends BaseJavaRefactoringAction {
   @Override
diff --git a/java/java-impl/src/com/intellij/refactoring/actions/RefactoringActionContextUtil.java b/java/java-impl/src/com/intellij/refactoring/actions/RefactoringActionContextUtil.java
new file mode 100644 (file)
index 0000000..8baec56
--- /dev/null
@@ -0,0 +1,37 @@
+// 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.refactoring.actions;
+
+import com.intellij.lang.java.JavaLanguage;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author yole
+ */
+public class RefactoringActionContextUtil {
+  public static boolean isJavaClassHeader(@NotNull PsiElement element) {
+    if (element.getLanguage() != JavaLanguage.INSTANCE) return false;
+    PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, false);
+    return psiClass != null && (element == psiClass || element == psiClass.getNameIdentifier() ||
+                                PsiTreeUtil.isAncestor(psiClass.getModifierList(), element, false) ||
+                                PsiTreeUtil.isAncestor(psiClass.getExtendsList(), element, false) ||
+                                PsiTreeUtil.isAncestor(psiClass.getImplementsList(), element, false));
+  }
+
+  @Nullable
+  public static PsiMethod getJavaMethodHeader(@Nullable PsiElement element) {
+    if (element == null) return null;
+    if (element.getLanguage() != JavaLanguage.INSTANCE) return null;
+    PsiMethod psiMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false);
+    if (psiMethod != null && (element == psiMethod || element == psiMethod.getNameIdentifier() ||
+                                 PsiTreeUtil.isAncestor(psiMethod.getModifierList(), element, false) ||
+                                 PsiTreeUtil.isAncestor(psiMethod.getParameterList(), element, false))) {
+      return psiMethod;
+    }
+    return null;
+  }
+}
index 3f09ff09d7bdc32ca310a7325403ee062e87703d..603c93231c218c0929878c404eccb201662972c8 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.intellij.refactoring.actions;
 
-import com.intellij.lang.java.JavaLanguage;
 import com.intellij.openapi.actionSystem.ActionPlaces;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.editor.Editor;
@@ -24,11 +23,9 @@ import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiMethod;
-import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.refactoring.RefactoringActionHandler;
 import com.intellij.refactoring.replaceConstructorWithBuilder.ReplaceConstructorWithBuilderHandler;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 public class ReplaceConstructorWithBuilderAction extends BaseJavaRefactoringAction{
   @Override
@@ -46,25 +43,12 @@ public class ReplaceConstructorWithBuilderAction extends BaseJavaRefactoringActi
       return false;
     }
     if (ActionPlaces.isPopupPlace(place) || place.equals(ActionPlaces.REFACTORING_QUICKLIST)) {
-      PsiMethod method = getJavaMethodHeader(elementAt);
+      PsiMethod method = RefactoringActionContextUtil.getJavaMethodHeader(elementAt);
       return method != null && method.isConstructor();
     }
     return true;
   }
 
-  @Nullable
-  public static PsiMethod getJavaMethodHeader(@Nullable PsiElement element) {
-    if (element == null) return null;
-    if (element.getLanguage() != JavaLanguage.INSTANCE) return null;
-    PsiMethod psiMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false);
-    if (psiMethod != null && (element == psiMethod || element == psiMethod.getNameIdentifier() ||
-                                 PsiTreeUtil.isAncestor(psiMethod.getModifierList(), element, false) ||
-                                 PsiTreeUtil.isAncestor(psiMethod.getParameterList(), element, false))) {
-      return psiMethod;
-    }
-    return null;
-  }
-
   @Override
   protected boolean isEnabledOnElements(@NotNull final PsiElement[] elements) {
     return false;
index 3cd07ba9ca8deaf8747cb8e81220e28ed011f0f1..a0062037d74d35eeae2a9df6f37bc4c913a2aa41 100644 (file)
@@ -45,7 +45,7 @@ public class ReplaceConstructorWithFactoryAction extends BaseJavaRefactoringActi
                                                         @NotNull Editor editor,
                                                         @NotNull PsiFile file,
                                                         @NotNull DataContext context) {
-    PsiMethod method = ReplaceConstructorWithBuilderAction.getJavaMethodHeader(element);
+    PsiMethod method = RefactoringActionContextUtil.getJavaMethodHeader(element);
     return (method != null &&
             method.isConstructor() &&
             acceptClass(method.getContainingClass())  ||
index 8ea608f6d713634277437be487293807c8dc537a..2590b1bc1116ed99d9376ebe5707381d853cdfce 100644 (file)
@@ -22,7 +22,6 @@ import com.intellij.openapi.editor.Editor;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
-import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.refactoring.RefactoringActionHandler;
 import com.intellij.refactoring.turnRefsToSuper.TurnRefsToSuperHandler;
 import org.jetbrains.annotations.NotNull;
@@ -45,20 +44,11 @@ public class TurnRefsToSuperAction extends BaseJavaRefactoringAction {
                                                         @NotNull DataContext context,
                                                         @NotNull String place) {
     if (ActionPlaces.isPopupPlace(place) || place.equals(ActionPlaces.REFACTORING_QUICKLIST)) {
-      return isJavaClassHeader(element);
+      return RefactoringActionContextUtil.isJavaClassHeader(element);
     }
     return super.isAvailableOnElementInEditorAndFile(element, editor, file, context, place);
   }
 
-  public static boolean isJavaClassHeader(@NotNull PsiElement element) {
-    if (element.getLanguage() != JavaLanguage.INSTANCE) return false;
-    PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, false);
-    return psiClass != null && (element == psiClass || element == psiClass.getNameIdentifier() ||
-                                PsiTreeUtil.isAncestor(psiClass.getModifierList(), element, false) ||
-                                PsiTreeUtil.isAncestor(psiClass.getExtendsList(), element, false) ||
-                                PsiTreeUtil.isAncestor(psiClass.getImplementsList(), element, false));
-  }
-
   @Override
   public RefactoringActionHandler getHandler(@NotNull DataContext dataContext) {
     return new TurnRefsToSuperHandler();
index 311842450e4d0eed5021d03c076a4e823d9e10d3..3662da4597ffba7f0d8918c8ef38ccde8c9cbcde 100644 (file)
@@ -38,6 +38,7 @@ import com.intellij.refactoring.RefactoringActionHandler;
 import com.intellij.refactoring.RefactoringBundle;
 import com.intellij.refactoring.util.CommonRefactoringUtil;
 import com.intellij.refactoring.util.RefactoringChangeUtil;
+import com.intellij.refactoring.util.RefactoringUtil;
 import com.intellij.refactoring.util.classMembers.ElementNeedsThis;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.IncorrectOperationException;
@@ -589,7 +590,8 @@ public class AnonymousToInnerHandler implements RefactoringActionHandler {
         final PsiElement resolved = reference.resolve();
         if (resolved instanceof PsiTypeParameter) {
           final PsiTypeParameterListOwner owner = ((PsiTypeParameter)resolved).getOwner();
-          if (owner != null && !PsiTreeUtil.isAncestor(myAnonClass, owner, false)) {
+          if (owner != null && !PsiTreeUtil.isAncestor(myAnonClass, owner, false) && 
+              (RefactoringUtil.isInStaticContext(owner, myTargetClass) || myMakeStatic)) {
             myTypeParametersToCreate.add((PsiTypeParameter)resolved);
           }
         }
index 9f27411253a93664f62e0546af78df49d32cd025..f87f6d5f1634ab8f4ae445dd1d95d0ffe1f99313 100644 (file)
@@ -242,7 +242,13 @@ public class TestIntegrationUtils {
     if (existingNames != null && !existingNames.add(name)) {
       int idx = 1;
       while (existingNames.contains(name)) {
-        final String newName = name + (idx++);
+        if (!name.startsWith("test")) {
+          name = "test" + StringUtil.capitalize(name);
+          if (existingNames.add(name)) {
+            break;
+          }
+        }
+        String newName = name + (idx++);
         if (existingNames.add(newName)) {
           name = newName;
           break;
index 9d0185a2a9154e978a769288942b1c8c732752d0..873274bc2ac224d448538782b2a40ed116198330 100644 (file)
@@ -176,7 +176,7 @@ public class CreateTestDialog extends DialogWrapper {
   }
 
   private String getDefaultLibraryName() {
-    return getProperties().getValue(DEFAULT_LIBRARY_NAME_PROPERTY);
+    return getProperties().getValue(DEFAULT_LIBRARY_NAME_PROPERTY, "JUnit5");
   }
 
   private String getLastSelectedSuperClassName(TestFramework framework) {
@@ -366,10 +366,6 @@ public class CreateTestDialog extends DialogWrapper {
       model.addElement(descriptor);
       if (hasTestRoots && descriptor.isLibraryAttached(myTargetModule)) {
         attachedLibraries.add(descriptor);
-
-        if (defaultLibrary == null) {
-          defaultDescriptor = descriptor;
-        }
       }
 
       if (Comparing.equal(defaultLibrary, descriptor.getName())) {
diff --git a/java/java-impl/src/inspectionDescriptions/ExplicitMinMaxCheck.html b/java/java-impl/src/inspectionDescriptions/ExplicitMinMaxCheck.html
new file mode 100644 (file)
index 0000000..bbbb092
--- /dev/null
@@ -0,0 +1,8 @@
+<html>
+<body>
+This inspection reports cases where minimum or maximum of two numbers can be calculated using
+<code>Math.max()</code> or <code>Math.min()</code> instead of doing it manually.
+<!-- tooltip end -->
+<p><small>New in 2019.2</small></p>
+</body>
+</html>
\ No newline at end of file
index 06d50a44de0e5074d4f53df9137ef3e6d96d79c5..9b6a13d808c87365cab3c4482fcce29473865923 100644 (file)
@@ -2,7 +2,6 @@
 package com.intellij.psi.impl.source.resolve.graphInference;
 
 import com.intellij.psi.*;
-import com.intellij.psi.infos.MethodCandidateInfo;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.psi.util.TypeConversionUtil;
@@ -34,11 +33,7 @@ public class PsiPolyExpressionUtil {
       return isInAssignmentOrInvocationContext(expression);
     }
     if (expression instanceof PsiMethodCallExpression) {
-      return isMethodCallPolyExpression(expression, expr -> {
-        final MethodCandidateInfo.CurrentCandidateProperties candidateProperties =
-          MethodCandidateInfo.getCurrentMethod(((PsiMethodCallExpression)expr).getArgumentList());
-        return candidateProperties != null ? candidateProperties.getMethod() : ((PsiMethodCallExpression)expr).resolveMethod();
-      });
+      return isMethodCallPolyExpression(expression, expr -> ((PsiMethodCallExpression)expr).resolveMethod());
     }
     if (expression instanceof PsiConditionalExpression) {
       final ConditionalKind conditionalKind = isBooleanOrNumeric(expression);
index 049802081148e3ea7c1ed59c2d511c95965a1958..bd033fa373268371c50ce7156836ebc655946f70 100644 (file)
@@ -2,7 +2,7 @@
 Value is always false (x > 6 && y > 10)
   Operand #1 of &&-chain is false (x > 6)
     Left operand is 5 (x)
-      'x' was assigned (5)
+      'x' was assigned to '5' (=)
  */
 
 class Test {
diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNotNull.java b/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNotNull.java
new file mode 100644 (file)
index 0000000..c1714d2
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+Value is always false (foo == null)
+  'foo' was assigned (=)
+    One of the following happens:
+      Expression cannot be null as it's newly created object (new String("foo"))
+      or expression cannot be null as it's newly created object (new String("bar"))
+ */
+
+import org.jetbrains.annotations.Nullable;
+
+class Test {
+
+  void test(boolean b) {
+    String foo = b ? new String("foo") : new String("bar");
+    if (<selection>foo == null</selection>) {
+      
+    }
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNumeric.java b/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNumeric.java
new file mode 100644 (file)
index 0000000..70f6d8c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+Value is always false (foo > 3)
+  One of the following happens:
+    Left operand is 1 (foo)
+      'foo' was assigned (=)
+    or left operand is 2 (foo)
+      'foo' was assigned (=)
+ */
+
+import org.jetbrains.annotations.Nullable;
+
+class Test {
+
+  void test(boolean b) {
+    int foo = b ? 1 : 2;
+    if (<selection>foo > 3</selection>) {
+      
+    }
+  }
+}
\ No newline at end of file
index aeda8421d7343f5f6dad3946b2b97f279d208679..8b27e41bb4b1ae57098623e6ccfd326a13d7b797 100644 (file)
@@ -1,6 +1,6 @@
 /*
 Value is always true (b)
-  'b' was assigned (true)
+  'b' was assigned to 'true' (=)
  */
 
 class Test {
index c0e285d885f5b30a050ff80dc7097b4b0749f4e1..fff9d8f7771dde0a7c5845e8e1926f64c3ff8a8f 100644 (file)
@@ -1,7 +1,7 @@
 /*
 Value is always false (s == null)
-  's' was assigned (s1)
-    Condition 's1 != null' was checked before (s1 == null)
+  's' was assigned (=)
+    's1' is known to be 'non-null' from line #8 (s1 == null)
  */
 class Test {
   void test(String s, String s1) {
index d8c52295a2230f376527ec846e7edeb539b8ee41..2e1873057cc167afc00e969fd3be299bea1071e0 100644 (file)
@@ -1,9 +1,9 @@
 /*
 Value is always false (b4)
-  'b4' was assigned (b3)
-    'b3' was assigned (b2)
-      'b2' was assigned (b1)
-        'b1' was assigned (b)
+  'b4' was assigned (=)
+    'b3' was assigned (=)
+      'b2' was assigned (=)
+        'b1' was assigned (=)
           'b == false' was established from condition (b)
  */
 import org.jetbrains.annotations.NotNull;
index 5c50466df0ae19884a459423e027821d73db0034..9a4e3275ac0538bb550cc24ea0c8b9b3f4c576ec 100644 (file)
@@ -1,9 +1,9 @@
 /*
 Value is always false (x == null)
   One of the following happens:
-    'x' was assigned (new Object())
+    'x' was assigned (=)
       Expression cannot be null as it's newly created object (new Object())
-    or 'x' was assigned ("foo")
+    or 'x' was assigned to '"foo"' (=)
       Expression cannot be null as it's literal ("foo")
  */
 
index 4ec0164c1e6012ca273fbc4c5c946a7ae32c7d22..f45a38a50fd74ea4d43ff6761ec2e0d7cf0c89a9 100644 (file)
@@ -1,10 +1,10 @@
 /*
 Value is always false (y == null)
-  'y' was assigned (x)
+  'y' was assigned (=)
     One of the following happens:
-      'x' was assigned (new Object())
+      'x' was assigned (=)
         Expression cannot be null as it's newly created object (new Object())
-      or 'x' was assigned ("foo")
+      or 'x' was assigned to '"foo"' (=)
         Expression cannot be null as it's literal ("foo")
  */
 
index 723134684363c7da1071e834a5cc1bd77192d23a..cf76c452591e508c137ce2b34e3ba310021d3624 100644 (file)
@@ -1,10 +1,10 @@
 /*
 Value is always true (j >= 0)
   Left operand is >= 0 (j)
-    'j' was assigned (i + 1)
+    'j' was assigned (=)
       Result of '+' is >= 0 (i + 1)
         Left operand is in {-1..Integer.MAX_VALUE-1} (i)
-          'i' was assigned (s.indexOf(' '))
+          'i' was assigned (=)
             Value is in {-1..Integer.MAX_VALUE-1} (s.indexOf(' '))
  */
 
index 3068cea4665eb08aa4036ef27c6a1f4c00adcbb1..fd9dc371bc76c0e2115a330858a519147efe2a81 100644 (file)
@@ -1,6 +1,6 @@
 /*
 Value is always false (s1 == null)
-  's1' was assigned (s.trim())
+  's1' was assigned (=)
     Method 'trim' is externally annotated as 'non-null' (trim)
  */
 class Test {
index dfd2f8826c6fa8ef9f4cedd511cb120bcb435e63..33911032b2250c4ce56c485a2410089a920d06ff 100644 (file)
@@ -1,6 +1,6 @@
 /*
 Value is always true ((s = new Object()) != null)
-  's' was assigned (new Object())
+  's' was assigned (=)
     Expression cannot be null as it's newly created object (new Object())
  */
 
index f04337b8c62be0d8088ccdf8573acc5528e03862..0d91a307f444981b6cb9af6ec9587ba9cf531b48 100644 (file)
@@ -1,6 +1,6 @@
 /*
 Value is always true (s != null)
-  's' was assigned (new Object())
+  's' was assigned (=)
     Expression cannot be null as it's newly created object (new Object())
  */
 
index 93672617a45c00cb97a52c376d6be8ec56e130d5..4037df331e944f2576696e341e75bf3feb18e4bc 100644 (file)
@@ -1,6 +1,6 @@
 /*
 Value is always true (null == s)
-  's' was assigned (null)
+  's' was assigned to 'null' (=)
  */
 import org.jetbrains.annotations.NotNull;
 
index 959ae680bb5639347911d279c8a140cbab03fe9d..8c3b99bf7971297b1696392ce21d527cd6ea50eb 100644 (file)
@@ -1,6 +1,6 @@
 /*
 May be null (s)
-  's' was assigned (loadString())
+  's' was assigned (=)
     Method 'loadString' is annotated as 'nullable' (@Nullable)
  */
 
index 0b29d755e77b33981fc21aaa6cf817e4eb76bba0..bcbea75779a7abf360bac64ee7f1a019a5118b49 100644 (file)
@@ -1,6 +1,6 @@
 /*
 May be null (foo)
-  'foo' was assigned (getFoo())
+  'foo' was assigned (=)
     Method 'getFoo' is annotated as 'nullable' (@Nullable)
  */
 
index 26168a3ac3779957837083af8dae7d10e3402107..48d4c494147149eae4741e2c3063d000a5c5bcd9 100644 (file)
@@ -1,6 +1,6 @@
 /*
 Value is always false (s == null)
-  Condition 's != null' was checked before (null == s)
+  's' is known to be 'non-null' from line #7 (null == s)
  */
 class Test {
   void test(String s) {
index 591e81dca8beb59011fc5568abd022785f9567ab..7d4dcdf7c21b0fbd6e728fdb1af2f00ca2a52939 100644 (file)
@@ -1,7 +1,7 @@
 /*
 Value is always false (s == s1)
-  's1' was assigned (null)
-  and condition 's != null' was checked before (null == s)
+  's' is known to be 'non-null' from line #8 (null == s)
+  and 's1' was assigned to 'null' (=)
  */
 class Test {
   void test(String s) {
index f69840cc093c1b01c9c8547b081816c2010e7fc0..c648bea36ae11ad2a0dfd23e60e48e86c7671feb 100644 (file)
@@ -6,14 +6,14 @@ Value is always true (x || (a+b)+(c+d)==10)
       Result of '+' is 10 ((a+b)+(c+d))
         Result of '+' is 3 (a+b)
           Left operand is 1 (a)
-            'a' was assigned (1)
+            'a' was assigned to '1' (=)
           and right operand is 2 (b)
-            'b' was assigned (2)
+            'b' was assigned to '2' (=)
         and result of '+' is 7 (c+d)
           Left operand is 3 (c)
-            'c' was assigned (3)
+            'c' was assigned to '3' (=)
           and right operand is 4 (d)
-            'd' was assigned (4)
+            'd' was assigned to '4' (=)
  */
 
 class Test {
diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/TrivialContract.java b/java/java-tests/testData/inspection/dataFlow/tracker/TrivialContract.java
new file mode 100644 (file)
index 0000000..44c8e12
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+Value is always false (list == null)
+  'list' was assigned (=)
+    According to contract, method 'loadList' always returns 'new' value (loadList)
+ */
+
+import java.util.List;
+import org.jetbrains.annotations.Contract;
+
+class Test {
+  @Contract("-> new")
+  List<String> loadList() {
+    return new ArrayList<>();
+  }
+
+  void test() {
+    List<String> list = loadList();
+    if(<selection>list == null</selection>) {}
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/afterAssignmentInReturn.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/afterAssignmentInReturn.java
new file mode 100644 (file)
index 0000000..ace9864
--- /dev/null
@@ -0,0 +1,9 @@
+// "Replace with 'Math.max'" "true"
+class Test {
+
+  int field;
+
+  int max(int i, int j) {
+      return field = Math.max(i, j);
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/afterConditional.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/afterConditional.java
new file mode 100644 (file)
index 0000000..6a06620
--- /dev/null
@@ -0,0 +1,9 @@
+// "Replace with 'Math.max'" "true"
+class Test {
+  void test(int a, int b) {
+      /*1*/
+      /*2*/
+      /*3*/
+      int c/*0*/ = (Math.max((a), (b)));
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/afterIf.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/afterIf.java
new file mode 100644 (file)
index 0000000..3ffb3f8
--- /dev/null
@@ -0,0 +1,11 @@
+// "Replace with 'Math.min'" "true"
+class Test {
+
+  void test(int a, int b) {
+    int c;
+      /*0*/
+      /*1*/
+      /*3*/
+      c = Math.min((a), (b))/*2*/;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/afterInnerConditional.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/afterInnerConditional.java
new file mode 100644 (file)
index 0000000..9ac53e9
--- /dev/null
@@ -0,0 +1,7 @@
+// "Replace with 'Math.max'" "true"
+class Test {
+
+  void test(int a, int b, int c) {
+    int d = a > b ? Math.max(a, c) : b;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/afterReturnFromIf.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/afterReturnFromIf.java
new file mode 100644 (file)
index 0000000..5aa80b2
--- /dev/null
@@ -0,0 +1,15 @@
+// "Replace with 'Math.max'" "true"
+class Test {
+
+  class A {
+    int field;
+
+    int getField() {
+      return field;
+    }
+  }
+
+  int getMax(A a, A b) {
+      return Math.max(a.getField(), b.getField());
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/afterSwitchInIf.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/afterSwitchInIf.java
new file mode 100644 (file)
index 0000000..d6d3ee8
--- /dev/null
@@ -0,0 +1,11 @@
+// "Replace with 'Math.min'" "true"
+class Test {
+
+  void test(int a, int b, String s) {
+    int c = switch (s) {
+      case "foo" -> {
+          break Math.min(b, a);
+      }
+    };
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeAssignmentInReturn.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeAssignmentInReturn.java
new file mode 100644 (file)
index 0000000..ad86848
--- /dev/null
@@ -0,0 +1,10 @@
+// "Replace with 'Math.max'" "true"
+class Test {
+
+  int field;
+
+  int max(int i, int j) {
+    if<caret>(i > j) return field = i;
+    else return field = j;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeConditional.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeConditional.java
new file mode 100644 (file)
index 0000000..4ceada3
--- /dev/null
@@ -0,0 +1,6 @@
+// "Replace with 'Math.max'" "true"
+class Test {
+  void test(int a, int b) {
+    int c/*0*/ = (((a) <caret> > /*1*/(b)) ? /*2*/(a) : /*3*/(b));
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeIf.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeIf.java
new file mode 100644 (file)
index 0000000..ba35db4
--- /dev/null
@@ -0,0 +1,11 @@
+// "Replace with 'Math.min'" "true"
+class Test {
+
+  void test(int a, int b) {
+    int c;
+    if<caret>/*0*/(((a) /*1*/< (b))) {
+      c = (a)/*2*/;
+    }
+    else c/*3*/ = (b);
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeInnerConditional.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeInnerConditional.java
new file mode 100644 (file)
index 0000000..d51a2ae
--- /dev/null
@@ -0,0 +1,7 @@
+// "Replace with 'Math.max'" "true"
+class Test {
+
+  void test(int a, int b, int c) {
+    int d = a > b ? <caret>a > c ? a : c : b;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeReturnFromIf.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeReturnFromIf.java
new file mode 100644 (file)
index 0000000..95536b8
--- /dev/null
@@ -0,0 +1,20 @@
+// "Replace with 'Math.max'" "true"
+class Test {
+
+  class A {
+    int field;
+
+    int getField() {
+      return field;
+    }
+  }
+
+  int getMax(A a, A b) {
+    if<caret> (a.getField() > b.getField()) {
+      return a.getField();
+    }
+    else {
+      return b.getField();
+    }
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeSideEffect.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeSideEffect.java
new file mode 100644 (file)
index 0000000..efa1bd5
--- /dev/null
@@ -0,0 +1,8 @@
+// "Fix all 'Explicit min/max check' problems in file" "false"
+class Test {
+
+  void test(int a, int b) {
+    int c = <caret>a++ > b ? a : b++;
+  }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeSwitchInIf.java b/java/java-tests/testData/inspection/explicitMinMaxCheck/beforeSwitchInIf.java
new file mode 100644 (file)
index 0000000..644d48d
--- /dev/null
@@ -0,0 +1,12 @@
+// "Replace with 'Math.min'" "true"
+class Test {
+
+  void test(int a, int b, String s) {
+    int c = switch (s) {
+      case "foo" -> {
+        if<caret>(b > a) break a;
+        else break b;
+      }
+    };
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/anonymousToInner/redundantTypeParameter.java b/java/java-tests/testData/refactoring/anonymousToInner/redundantTypeParameter.java
new file mode 100644 (file)
index 0000000..3d183f8
--- /dev/null
@@ -0,0 +1,13 @@
+
+import java.util.function.Consumer;
+
+class AnonymToInnerWIthGeneric<T> {
+    private final Consumer<T> our = System.out::println;
+
+    private final Consumer<T> my = new Cons<caret>umer<T>() {
+        @Override
+        public void accept(T t) {
+            our.accept(t);
+        }
+    };
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/anonymousToInner/redundantTypeParameter_after.java b/java/java-tests/testData/refactoring/anonymousToInner/redundantTypeParameter_after.java
new file mode 100644 (file)
index 0000000..9a01150
--- /dev/null
@@ -0,0 +1,15 @@
+
+import java.util.function.Consumer;
+
+class AnonymToInnerWIthGeneric<T> {
+    private final Consumer<T> our = System.out::println;
+
+    private final Consumer<T> my = new MyConsumer();
+
+    private class MyConsumer implements Consumer<T> {
+        @Override
+        public void accept(T t) {
+            our.accept(t);
+        }
+    }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/anonymousToInner/requiredTypeParameter.java b/java/java-tests/testData/refactoring/anonymousToInner/requiredTypeParameter.java
new file mode 100644 (file)
index 0000000..3c385ed
--- /dev/null
@@ -0,0 +1,13 @@
+
+import java.util.function.Consumer;
+
+class AnonymToInnerWIthGeneric<T> {
+    private final Consumer<T> our = System.out::println;
+
+    private final Consumer<T> my = new Cons<caret>umer<T>() {
+        @Override
+        public void accept(T t) {
+            //our.accept(t);
+        }
+    };
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/anonymousToInner/requiredTypeParameter_after.java b/java/java-tests/testData/refactoring/anonymousToInner/requiredTypeParameter_after.java
new file mode 100644 (file)
index 0000000..0ddeca4
--- /dev/null
@@ -0,0 +1,15 @@
+
+import java.util.function.Consumer;
+
+class AnonymToInnerWIthGeneric<T> {
+    private final Consumer<T> our = System.out::println;
+
+    private final Consumer<T> my = new MyConsumer<>();
+
+    private static class MyConsumer<T> implements Consumer<T> {
+        @Override
+        public void accept(T t) {
+            //our.accept(t);
+        }
+    }
+}
\ No newline at end of file
index e6a5170a1421205b09f8791bd1b7ec8565d15fa4..50be34f76f0592172382084235bf9321787644fb 100644 (file)
@@ -149,4 +149,7 @@ public class DataFlowInspectionTrackerTest extends LightCodeInsightFixtureTestCa
   public void testNpeSimple() { doTest(); }
   public void testNpeAnnotation() { doTest(); }
   public void testNpeWithCast() { doTest(); }
+  public void testAssignTernaryNotNull() { doTest(); }
+  public void testAssignTernaryNumeric() { doTest(); }
+  public void testTrivialContract() { doTest(); }
 }
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/ExplicitMinMaxCheckInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/ExplicitMinMaxCheckInspectionTest.java
new file mode 100644 (file)
index 0000000..34b808b
--- /dev/null
@@ -0,0 +1,31 @@
+// 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.java.codeInspection;
+
+import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
+import com.intellij.codeInspection.ExplicitMinMaxCheckInspection;
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.testFramework.LightProjectDescriptor;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @see com.intellij.codeInspection.ExplicitMinMaxCheckInspection
+ */
+public class ExplicitMinMaxCheckInspectionTest extends LightQuickFixParameterizedTestCase {
+  @NotNull
+  @Override
+  protected LocalInspectionTool[] configureLocalInspectionTools() {
+    return new LocalInspectionTool[]{new ExplicitMinMaxCheckInspection()};
+  }
+
+  @Override
+  protected String getBasePath() {
+    return "/inspection/explicitMinMaxCheck";
+  }
+
+  @NotNull
+  @Override
+  protected LightProjectDescriptor getProjectDescriptor() {
+    return LightCodeInsightFixtureTestCase.JAVA_12;
+  }
+}
index eae5ae0c1cd88c1445c248cf82fa854093d630a2..2855f703850bd217f0d1c1d1a09359c64245d028 100644 (file)
@@ -83,7 +83,7 @@ public class GotoImplementationHandlerTest extends JavaCodeInsightFixtureTestCas
     assertEquals(2, impls.length);
   }
 
-  public void testToStringOnUnqualified() {
+  public void testToStringOnUnqualifiedPerformance() {
     @Language("JAVA")
     String fileText = "public class Fix {\n" +
                   "    {\n" +
@@ -111,7 +111,7 @@ public class GotoImplementationHandlerTest extends JavaCodeInsightFixtureTestCas
      }).usesAllCPUCores().assertTiming();
   }
 
-  public void testToStringOnQualified() {
+  public void testToStringOnQualifiedPerformance() {
     @Language("JAVA")
     String fileText = "public class Fix {\n" +
                   "    {\n" +
index c6356ef480b6619b4e26416141cd3fdb2fdc78fe..74fb11f99b4228b57cf27fd14da5734d16af42ec 100644 (file)
@@ -47,6 +47,14 @@ public class AnonymousToInnerTest extends LightCodeInsightTestCase {
     doTest("MyPredicate", true);
   }
   
+  public void testRedundantTypeParameter() {
+    doTest("MyConsumer", false);
+  }
+  
+  public void testRequiredTypeParameter() {
+    doTest("MyConsumer", true);
+  }
+  
   public void testCanBeStatic() {
     configureByFile(TEST_ROOT + getTestName(true) + ".java");
     AnonymousToInnerHandler handler = new AnonymousToInnerHandler(){
index 2a5767fb341b66ae73bbae08186a0a637ee72a3f..6aad9805096448e447e70dd6977cad4c90dcdd77 100644 (file)
@@ -287,7 +287,7 @@ public class EditorTypingAndNavigationUndoTest extends EditorUndoTestCase {
     Ref<String> message = new Ref<>();
     Messages.setTestDialog(new TestDialog() {
       @Override
-      public int show(String m) {
+      public int show(@NotNull String m) {
         message.set(m);
         return Messages.YES;
       }
index 3683c8ff055329d28b4cde0c953478cc175f378f..f59aa28e0520f597a71bfa77995f8927fef340bf 100644 (file)
@@ -78,7 +78,7 @@ public class GlobalUndoTest extends UndoTestCase implements TestDialog {
   }
 
   @Override
-  public int show(String message) {
+  public int show(@NotNull String message) {
     myConfirmationWasRequested = true;
     return 0;
   }
diff --git a/java/java-tests/testSrc/com/intellij/testIntegration/GenerateMissedTestsTest.java b/java/java-tests/testSrc/com/intellij/testIntegration/GenerateMissedTestsTest.java
new file mode 100644 (file)
index 0000000..9fccbc3
--- /dev/null
@@ -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.testIntegration;
+
+import com.intellij.execution.junit.JUnit4Framework;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.refactoring.util.classMembers.MemberInfo;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import com.intellij.testIntegration.createTest.JavaTestGenerator;
+
+import java.util.List;
+
+public class GenerateMissedTestsTest extends LightCodeInsightFixtureTestCase {
+  public void testConflictingObjectNames() {
+    PsiClass srcClass = myFixture.addClass("public class Source { @Override public int hashCode() { return 0;}}");
+    PsiClass targetClass = ((PsiJavaFile)myFixture.configureByText("MyTest.java", "public class MyTest {}")).getClasses()[0];
+    List<MemberInfo> infos = TestIntegrationUtils.extractClassMethods(srcClass, true);
+    doTest(srcClass, targetClass, infos, new JUnit4Framework());
+    myFixture.checkResult("public class MyTest {\n" +
+                          "    @org.junit.Test\n" +
+                          "    public void testHashCode() {\n" +
+                          "    }\n" +
+                          "}", true);
+    //repeat
+    doTest(srcClass, targetClass, infos, new JUnit4Framework());
+    myFixture.checkResult("public class MyTest {\n" +
+                          "    @org.junit.Test\n" +
+                          "    public void testHashCode() {\n" +
+                          "    }\n\n" +
+                          "    @org.junit.Test\n" +
+                          "    public void testHashCode1() {\n" +
+                          "    }\n" +
+                          "}", true);
+  }
+
+  private void doTest(PsiClass srcClass, PsiClass targetClass, List<MemberInfo> infos, JUnit4Framework framework) {
+    WriteCommandAction.runWriteCommandAction(myFixture.getProject(),
+                                             () -> JavaTestGenerator.addTestMethods(getEditor(),
+                                                                                    targetClass, srcClass, framework,
+                                                                                    infos, false, false));
+  }
+}
index 75980c93b05f3830e2f2b8aead886810e85c81f5..08584124d808943672df8dde9688d8534770934f 100644 (file)
@@ -127,18 +127,18 @@ public abstract class ProjectWizardTestCase<T extends AbstractProjectWizard> ext
     return createModuleFromWizard(project);
   }
 
-  protected Module createModuleFromWizard(@NotNull Project project) {
+  private Module createModuleFromWizard(@NotNull Project project) {
     return new NewModuleAction().createModuleFromWizard(project, null, myWizard);
   }
 
-  protected void runWizard(@NotNull String group,
-                           @Nullable final String name,
-                           @Nullable Project project,
-                           @Nullable final Consumer<? super Step> adjuster) throws IOException {
+  private void runWizard(@NotNull String group,
+                         @Nullable final String name,
+                         @Nullable Project project,
+                         @Nullable final Consumer<? super Step> adjuster) throws IOException {
     createWizard(project);
     ProjectTypeStep step = (ProjectTypeStep)myWizard.getCurrentStepObject();
     if (!step.setSelectedTemplate(group, name)) {
-      throw new IllegalArgumentException(group + '/' + name + " template not found, available groups " + step.availableTemplateGroupsToString());
+      throw new IllegalArgumentException(group + '/' + name + " template not found. Available groups: " + step.availableTemplateGroupsToString());
     }
 
     runWizard(step1 -> {
@@ -151,7 +151,7 @@ public abstract class ProjectWizardTestCase<T extends AbstractProjectWizard> ext
     });
   }
 
-  protected void runWizard(@Nullable Consumer<? super Step> adjuster) {
+  private void runWizard(@Nullable Consumer<? super Step> adjuster) {
     while (true) {
       ModuleWizardStep currentStep = myWizard.getCurrentStepObject();
       if (adjuster != null) {
@@ -236,7 +236,7 @@ public abstract class ProjectWizardTestCase<T extends AbstractProjectWizard> ext
     return ContainerUtil.getFirstItem(ImportModuleAction.createFromWizard(project, myWizard));
   }
 
-  private static <T> T computeInWriteSafeContext(Supplier<T> supplier) {
+  private static <T> T computeInWriteSafeContext(Supplier<? extends T> supplier) {
     Ref<T> module = Ref.create();
     ApplicationManager.getApplication().invokeLater(() -> module.set(supplier.get()));
     UIUtil.dispatchAllInvocationEvents();
index 390fbdd6ca8d8586fca86b20fa817d84db834d16..e7342c43c6c3a459fe31b59e28d366e87d37d1bf 100644 (file)
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.jps.model.library.sdk;
 
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.model.JpsElement;
 import org.jetbrains.jps.model.JpsElementReference;
 import org.jetbrains.jps.model.library.JpsTypedLibrary;
@@ -23,5 +24,6 @@ import org.jetbrains.jps.model.library.JpsTypedLibrary;
  * @author nik
  */
 public interface JpsSdkReference<P extends JpsElement> extends JpsElementReference<JpsTypedLibrary<JpsSdk<P>>> {
+  @NotNull
   String getSdkName();
 }
index 3822a0d9128b444e13773663fe957bf1c151717e..9a5e9207ef942082e2f1c4ffa8404d2034903587 100644 (file)
@@ -30,6 +30,7 @@ public abstract class JpsNamedElementReferenceBase<S extends JpsNamedElement, T
   extends JpsCompositeElementBase<Self> implements JpsElementReference<T> {
   private static final JpsElementChildRole<JpsElementReference<? extends JpsCompositeElement>> PARENT_REFERENCE_ROLE = JpsElementChildRoleBase
     .create("parent");
+  @NotNull
   protected final String myElementName;
 
   protected JpsNamedElementReferenceBase(@NotNull String elementName, @NotNull JpsElementReference<? extends JpsCompositeElement> parentReference) {
index fdc678f7b820799c532180e2da7283d09aa76cbd..a9fcd9c57aa64b3f24e5893817c59c81f4345609 100644 (file)
@@ -53,6 +53,7 @@ public class JpsWrappedJavaSdkReferenceImpl extends JpsCompositeElementBase<JpsW
     return new JpsWrappedJavaSdkReferenceImpl(this);
   }
 
+  @NotNull
   @Override
   public String getSdkName() {
     JpsTypedLibrary<JpsSdk<JpsDummyElement>> sdk = resolve();
index a5b25c119b6b498154ea767bd44d2fe91692aff9..f1ad771012fe11455c5137ff23ff65e5897c8b55 100644 (file)
@@ -96,7 +96,7 @@
                    replace="&quot;jscsConfig&quot; : {&quot;$ref&quot;: &quot;http://json.schemastore.org/jscsrc#&quot;},${line.separator}  &quot;publishConfig&quot;" />
     <replaceregexp file="${idea.project.home}/plugins/NodeJS/src/com/jetbrains/nodejs/packageJson/packageJsonSchema.json"
                    match="&quot;publishConfig&quot;"
-                   replace="&quot;browserslist&quot; : {&quot;type&quot;: &quot;array&quot;, &quot;items&quot;: {&quot;type&quot;: &quot;string&quot;}, &quot;description&quot;: &quot;List of Browserslist queries&quot;},${line.separator}  &quot;publishConfig&quot;" />
+                   replace="&quot;browserslist&quot; : {&quot;oneOf&quot;: [{&quot;type&quot;: &quot;array&quot;, &quot;items&quot;: {&quot;type&quot;: &quot;string&quot;}}, {&quot;type&quot;: &quot;object&quot;, &quot;additionalProperties&quot;: {&quot;type&quot;: &quot;array&quot;, &quot;items&quot;: {&quot;type&quot;: &quot;string&quot;}}}] , &quot;description&quot;: &quot;List of Browserslist queries&quot;},${line.separator}  &quot;publishConfig&quot;" />
   </target>
 
   <target name="js_schemas">
diff --git a/jvm/jvm-analysis-api/src/com/intellij/codeInspection/NlsCapitalizationUtil.java b/jvm/jvm-analysis-api/src/com/intellij/codeInspection/NlsCapitalizationUtil.java
new file mode 100644 (file)
index 0000000..42e9f78
--- /dev/null
@@ -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.codeInspection;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class NlsCapitalizationUtil {
+
+  public static boolean isCapitalizationSatisfied(String value, Nls.Capitalization capitalization) {
+    if (StringUtil.isEmpty(value) || capitalization == Nls.Capitalization.NotSpecified) {
+      return true;
+    }
+    value = value.replace("&", "");
+    return capitalization == Nls.Capitalization.Title
+           ? StringUtil.wordsToBeginFromUpperCase(value).equals(value)
+           : checkSentenceCapitalization(value);
+  }
+
+  private static boolean checkSentenceCapitalization(@NotNull String value) {
+    List<String> words = StringUtil.split(value, " ");
+    final int wordCount = words.size();
+    if (wordCount == 0) return true;
+
+    if (Character.isLetter(words.get(0).charAt(0)) && !isCapitalizedWord(words.get(0))) return false;
+    if (wordCount == 1) return true;
+
+    int capitalized = 1;
+    for (int i = 1; i < wordCount; i++) {
+      String word = words.get(i);
+      if (isCapitalizedWord(word)) {
+        // check for abbreviations like 'C', 'SQL', 'I18n'
+        if (word.length() == 1 || !Character.isLowerCase(word.charAt(1))) {
+          continue;
+        }
+        capitalized++;
+      }
+    }
+
+    // "Start service"
+    if (capitalized == 1 && wordCount == 2) return true;
+
+    final double ratio = ((double)capitalized - 1) / wordCount;
+    return ratio <= 0.4; // allow reasonable amount of capitalized words
+  }
+
+  private static boolean isCapitalizedWord(String word) {
+    return !word.isEmpty() && Character.isLetter(word.charAt(0)) && Character.isUpperCase(word.charAt(0));
+  }
+
+  @NotNull
+  public static String fixValue(String string, Nls.Capitalization capitalization) {
+    return capitalization == Nls.Capitalization.Title
+           ? StringUtil.wordsToBeginFromUpperCase(string)
+           : StringUtil.capitalize(StringUtil.wordsToBeginFromLowerCase(string));
+  }
+}
diff --git a/jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/NlsCapitalizationUtilTest.java b/jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/NlsCapitalizationUtilTest.java
new file mode 100644 (file)
index 0000000..faf1b3c
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2019 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInspection;
+
+import junit.framework.TestCase;
+import org.jetbrains.annotations.Nls;
+
+import static com.intellij.codeInspection.NlsCapitalizationUtil.isCapitalizationSatisfied;
+
+public class NlsCapitalizationUtilTest extends TestCase {
+
+  public void testEmptyValue() {
+    assertSentence("");
+    assertTitle("");
+  }
+
+  public void testSentence() {
+    assertSentence("Word");
+    assertSentence("Minimal sentence");
+    assertSentence("A bit more normal sentence");
+  }
+
+  public void testSentenceNotSatisfied() {
+    assertNotCapitalization("all lowercase", Nls.Capitalization.Sentence);
+    assertNotCapitalization("All Uppercase", Nls.Capitalization.Sentence);
+  }
+
+  public void testSentenceIgnoreUppercaseWords() {
+    assertSentence("Fix C issues");
+    assertSentence("Fix SQL issues");
+    assertSentence("Fix I18n issues");
+  }
+
+  public void testSentenceIgnoreNonLetterWords() {
+    assertSentence("@charset is invalid");
+    assertSentence("Add 'this' qualifier");
+  }
+
+  public void testSentenceUppercaseWordsBelowThreshold() {
+    assertSentence("One Two three");
+    assertSentence("Two Uppercase three lower case");
+    assertSentence("Three Uppercase Words two lowercase");
+    assertSentence("Please select the configuration file (usually named IntelliLang.xml) to import.");
+  }
+
+  public void testSentenceTooManyUppercaseWords() {
+    assertNotCapitalization("Four Upper Case Words two lowercase", Nls.Capitalization.Sentence);
+  }
+  public void testTitle() {
+    assertTitle("Word");
+    assertTitle("Word Two");
+    assertTitle("Word Two   SomeSpaces");
+  }
+
+  public void testTitleNotSatisfied() {
+    assertNotCapitalization("lowercase", Nls.Capitalization.Title);
+    assertNotCapitalization("Word lowercase", Nls.Capitalization.Title);
+  }
+
+  public void testFixValueSentence() {
+    assertEquals("First word", NlsCapitalizationUtil.fixValue("First Word", Nls.Capitalization.Sentence));
+  }
+
+  public void testFixValueTitle() {
+    assertEquals("Upper Case", NlsCapitalizationUtil.fixValue("upper case", Nls.Capitalization.Title));
+  }
+
+  private static void assertSentence(String value) {
+    assertCapitalization(value, Nls.Capitalization.Sentence);
+  }
+
+  private static void assertTitle(String value) {
+    assertCapitalization(value, Nls.Capitalization.Title);
+  }
+
+  private static void assertCapitalization(String value, Nls.Capitalization capitalization) {
+    assertTrue("'" + value + "' does not satisfy " + capitalization, isCapitalizationSatisfied(value, capitalization));
+  }
+
+  private static void assertNotCapitalization(String value, Nls.Capitalization capitalization) {
+    assertFalse("'" + value + "' should not satisfy " + capitalization, isCapitalizationSatisfied(value, capitalization));
+  }
+}
\ No newline at end of file
index 29e63c37dd7d6fff171b1fa6c103f4b62e162f22..38ec8cddf0dcb21c704c4346197dad023b879de7 100644 (file)
@@ -79,8 +79,9 @@ abstract class BuildContext implements CompilationContext {
 
   /**
    * Execute a build step or skip it if {@code stepId} is included into {@link BuildOptions#buildStepsToSkip}
+   * @return {@code true} if the step was executed
    */
-  abstract void executeStep(String stepMessage, String stepId, Closure step)
+  abstract boolean executeStep(String stepMessage, String stepId, Closure step)
 
   abstract boolean shouldBuildDistributions()
 
index d8626b244d7be44e3b865a635632920ab3cb1881..0d83ef8f2be32df0282d59b93cd3923fe65120db 100644 (file)
@@ -58,6 +58,8 @@ class BuildOptions {
   static final String CROSS_PLATFORM_DISTRIBUTION_STEP = "cross_platform_dist"
   /** Toolbox links generator step */
   static final String TOOLBOX_LITE_GEN_STEP = "toolbox_lite_gen"
+  /** Generate files containing lists of used third-party libraries */
+  static final String THIRD_PARTY_LIBRARIES_LIST_STEP = "third_party_libraries"
 
   /**
    * Pass 'true' to this system property to produce an additional .dmg archive for macOS without bundled JRE.
index fc6cf0277f398c4eac6ae54eaacfdfe344879255..2d3e94cc7907e5162f28c0f0a24d8016e38b61fa 100644 (file)
@@ -220,7 +220,7 @@ class BuildContextImpl extends BuildContext {
   }
 
   @Override
-  void executeStep(String stepMessage, String stepId, Closure step) {
+  boolean executeStep(String stepMessage, String stepId, Closure step) {
     if (options.buildStepsToSkip.contains(stepId)) {
       messages.info("Skipping '$stepMessage'")
     }
index bfa3946baf0c16f8505a3ca6e92cb5b331fd2300..667b1a3e23ba67b7c9b2bd5b0eaa4a617347ea14 100644 (file)
@@ -198,9 +198,7 @@ class DistributionJARsBuilder {
     buildBundledPlugins()
     buildOsSpecificBundledPlugins()
     buildNonBundledPlugins()
-    if ("false" != System.getenv("BUILD_THIRD_PARTY_LIB_LIST")) {
-      buildThirdPartyLibrariesList()
-    }
+    buildThirdPartyLibrariesList()
 
     def loadingOrderFilePath = buildContext.productProperties.productLayout.classesLoadingOrderFilePath
     if (loadingOrderFilePath != null) {
@@ -302,7 +300,7 @@ class DistributionJARsBuilder {
   }
 
   private void buildThirdPartyLibrariesList() {
-    buildContext.messages.block("Generate table of licenses for used third-party libraries") {
+    buildContext.executeStep("Generate table of licenses for used third-party libraries", BuildOptions.THIRD_PARTY_LIBRARIES_LIST_STEP) {
       def generator = LibraryLicensesListGenerator.create(buildContext.messages,
                                                           buildContext.project,
                                                           buildContext.productProperties.allLibraryLicenses,
@@ -337,7 +335,9 @@ class DistributionJARsBuilder {
       layoutBuilder.patchModuleOutput("intellij.platform.resources", FileUtil.toSystemIndependentName(patchedKeyMapDir.absolutePath))
     }
 
-    buildByLayout(layoutBuilder, platform, buildContext.paths.distAll, platform.moduleJars, [])
+    buildContext.messages.block("Build platform JARs in lib directory") {
+      buildByLayout(layoutBuilder, platform, buildContext.paths.distAll, platform.moduleJars, [])
+    }
 
     if (buildContext.proprietaryBuildTools.scrambleTool != null) {
       def forbiddenJarNames = buildContext.proprietaryBuildTools.scrambleTool.namesOfJarsRequiredToBeScrambled
@@ -363,7 +363,9 @@ class DistributionJARsBuilder {
   private void buildBundledPlugins() {
     def layoutBuilder = createLayoutBuilder()
     def allPlugins = getPluginsByModules(buildContext, buildContext.productProperties.productLayout.bundledPluginModules)
-    buildPlugins(layoutBuilder, allPlugins.findAll { satisfiesBundlingRequirements(it, null) }, "$buildContext.paths.distAll/plugins")
+    buildContext.messages.block("Build bundled plugins") {
+      buildPlugins(layoutBuilder, allPlugins.findAll { satisfiesBundlingRequirements(it, null) }, "$buildContext.paths.distAll/plugins")
+    }
     usedModules.addAll(layoutBuilder.usedModules)
   }
 
@@ -385,10 +387,12 @@ class DistributionJARsBuilder {
           satisfiesBundlingRequirements(it, osFamily)
         }
 
-      if (!osSpecificPlugins.isEmpty()) {
+      if (!osSpecificPlugins.isEmpty() && buildContext.shouldBuildDistributionForOS(osFamily.osId)) {
         def layoutBuilder = createLayoutBuilder()
-        buildPlugins(layoutBuilder, osSpecificPlugins,
-                     "$buildContext.paths.buildOutputRoot/dist.$osFamily.distSuffix/plugins")
+        buildContext.messages.block("Build bundled plugins for $osFamily.osName") {
+          buildPlugins(layoutBuilder, osSpecificPlugins,
+                       "$buildContext.paths.buildOutputRoot/dist.$osFamily.distSuffix/plugins")
+        }
         usedModules.addAll(layoutBuilder.usedModules)
       }
     }
index 79b6e96fa465c50afed90d6db2c4386669bb8f1f..59c2cfecfd0cc61be45339a652ca282d567dfc90 100644 (file)
@@ -133,10 +133,14 @@ class BuildMessagesImpl implements BuildMessages {
 
   @Override
   <V> V block(String blockName, Closure<V> body) {
+    long start = System.currentTimeMillis()
     try {
       blockNames.push(blockName)
       processMessage(new LogMessage(LogMessage.Kind.BLOCK_STARTED, blockName))
-      return body()
+      def result = body()
+      long elapsedTime = System.currentTimeMillis() - start
+      debug("${blockNames.join(" > ")} finished in ${elapsedTime}ms")
+      return result
     }
     catch (IntelliJBuildException e) {
       throw e
index ad4ea565c164aa14989cd60485c367ae0432f30d..e230818c12e72f5bd21c6eb71f507c7cc358b74a 100644 (file)
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="module" module-name="intellij.platform.jps.model" />
     <orderEntry type="module" module-name="intellij.platform.jps.model.impl" />
-    <orderEntry type="module" module-name="intellij.platform.jps.model.serialization" />
     <orderEntry type="library" name="kotlin-stdlib-jdk8" level="project" />
     <orderEntry type="module" module-name="intellij.platform.util" />
     <orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
     <orderEntry type="module" module-name="intellij.platform.testFramework" scope="PROVIDED" />
     <orderEntry type="library" name="http-client" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="commons-imaging" level="project" />
+    <orderEntry type="module" module-name="intellij.platform.projectModel.impl" />
   </component>
 </module>
\ No newline at end of file
index 608f4fbe36196050eba0ee63631227b1ca83535d..10e5ee90f9e7b68f508bfb4dd6091e8c7c22cd79 100644 (file)
@@ -4,11 +4,7 @@ package org.jetbrains.intellij.build.images.sync
 import org.jetbrains.intellij.build.images.ImageExtension
 import org.jetbrains.intellij.build.images.imageSize
 import org.jetbrains.intellij.build.images.isImage
-import org.jetbrains.jps.model.java.JavaResourceRootType
-import org.jetbrains.jps.model.java.JavaSourceRootType
-import org.jetbrains.jps.model.serialization.JpsSerializationManager
 import java.io.File
-import java.io.IOException
 import java.nio.file.Files
 import java.nio.file.Path
 import java.util.function.Consumer
@@ -241,7 +237,8 @@ private fun removedByDesigners(context: Context, addedByDev: Collection<String>,
                                iconsRepo: File, iconsDir: String) = addedByDev.parallelStream().filter {
   val byDesigners = latestChangeTime("$iconsDir$it", iconsRepo)
   // latest changes are made by designers
-  byDesigners > 0 && latestChangeTime(context.devIcons[it]) < byDesigners
+  val latestChangeTime = latestChangeTime(context.devIcons[it])
+  latestChangeTime > 0 && byDesigners > 0 && latestChangeTime < byDesigners
 }.toList()
 
 private fun removedByDev(context: Context,
@@ -264,12 +261,10 @@ private fun latestChangeTime(file: String, repos: Collection<File>): Long {
   return -1
 }
 
-private fun modifiedByDev(context: Context, modified: Collection<String>) = modified.parallelStream()
+private fun modifiedByDev(context: Context, modified: Collection<String>) = modified.parallelStream().filter {
   // latest changes are made by developers
-  .filter { latestChangeTime(context.icons[it]) < latestChangeTime(context.devIcons[it]) }
-  .collect(Collectors.toList())
+  val latestChangeTimeByDev = latestChangeTime(context.devIcons[it])
+  latestChangeTimeByDev > 0 && latestChangeTime(context.icons[it]) < latestChangeTimeByDev
+}.collect(Collectors.toList())
 
-private fun latestChangeTime(obj: GitObject?) =
-  latestChangeTime(obj!!.path, obj.repo).also {
-    if (it <= 0) error(obj.toString())
-  }
\ No newline at end of file
+private fun latestChangeTime(obj: GitObject?) = latestChangeTime(obj!!.path, obj.repo)
\ No newline at end of file
index a8b67fa992135e6bc59a190caf67147a33ed5bbc..c72899c147a09877d6d250ec463995020a9813ba 100644 (file)
@@ -171,7 +171,7 @@ internal fun getOriginUrl(repo: File): String {
       }
     }
   }
-  return origins[repo]!!
+  return origins.getValue(repo)
 }
 
 @Volatile
@@ -188,6 +188,9 @@ internal fun latestChangeCommit(path: String, repo: File): CommitInfo? {
       if (!latestChangeCommits.containsKey(file)) {
         val commitInfo = commitInfo(repo, "--", path)
         if (commitInfo != null) {
+          if (commitInfo.parents.size == 6 && commitInfo.subject.contains("Merge all repositories")) {
+            return null
+          }
           synchronized(latestChangeCommitsGuard) {
             latestChangeCommits += file to commitInfo
           }
@@ -196,7 +199,7 @@ internal fun latestChangeCommit(path: String, repo: File): CommitInfo? {
       }
     }
   }
-  return latestChangeCommits[file]!!
+  return latestChangeCommits.getValue(file)
 }
 
 /**
@@ -272,7 +275,7 @@ internal fun head(repo: File): String {
       }
     }
   }
-  return heads[repo]!!
+  return heads.getValue(repo)
 }
 
 internal fun commitInfo(repo: File, vararg args: String): CommitInfo? {
index aec89549172e5ae775b2664100c98b1365e3df13..695bab2a2103592b241ff140fdd6b61b1b1c4dbf 100644 (file)
@@ -183,14 +183,14 @@ internal fun assignInvestigation(context: Context): Investigator? =
       } to context.devCommitsToSync
     }
     else triggeredBy() to context.iconsCommitsToSync
-    var reviews = emptyList<String>()
+    val reviews = mutableListOf<String>()
     if (commits.isEmpty()) {
       if (context.commitsAlreadyInReview.isEmpty()) {
         log("No commits, no investigation")
         return@callSafely null
       }
       context.commitsAlreadyInReview.keys.maxBy(CommitInfo::timestamp)?.let { latest ->
-        val review = context.commitsAlreadyInReview[latest]!!
+        val review = context.commitsAlreadyInReview.getValue(latest)
         log("Assigning investigation to ${latest.committerEmail} as author of latest change ${latest.hash} under review $review")
         investigator = latest.committerEmail
         commits = context.commitsAlreadyInReview.keys
index 14b92be3c6ae9118a3b75eebd5041105132422ac..66ca80f0fc1dc940267a3127ba239f8f2479d4f4 100644 (file)
@@ -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 org.jetbrains.ide
 
 import com.intellij.ide.impl.ProjectUtil.focusProjectWindow
@@ -72,7 +72,7 @@ internal class OpenFileHttpService : RestService() {
 
     val apiRequest: OpenFileRequest
     if (request.method() === HttpMethod.POST) {
-      apiRequest = gson.value.fromJson(createJsonReader(request), OpenFileRequest::class.java)
+      apiRequest = gson.fromJson(createJsonReader(request), OpenFileRequest::class.java)
     }
     else {
       apiRequest = OpenFileRequest()
@@ -82,7 +82,7 @@ internal class OpenFileHttpService : RestService() {
       apiRequest.focused = getBooleanParameter("focused", urlDecoder, true)
     }
 
-    val prefixLength = 1 + PREFIX.length + 1 + serviceName.length + 1
+    val prefixLength = 1 + PREFIX.length + 1 + getServiceName().length + 1
     val path = urlDecoder.path()
     if (path.length > prefixLength) {
       val matcher = LINE_AND_COLUMN.matcher(path).region(prefixLength, path.length)
@@ -104,7 +104,10 @@ internal class OpenFileHttpService : RestService() {
     }
 
     val promise = openFile(apiRequest, context, request) ?: return null
-    promise.onSuccess { sendStatus(HttpResponseStatus.OK, keepAlive, channel) }
+    promise
+      .onSuccess {
+        sendOk(request, context)
+      }
       .onError {
         if (it === NOT_FOUND) {
           // don't expose file status
diff --git a/platform/built-in-server/src/org/jetbrains/ide/OpenSettingsJbProtocolService.kt b/platform/built-in-server/src/org/jetbrains/ide/OpenSettingsJbProtocolService.kt
new file mode 100644 (file)
index 0000000..aef37f8
--- /dev/null
@@ -0,0 +1,35 @@
+// 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 org.jetbrains.ide
+
+import com.intellij.ide.ui.search.SearchableOptionsRegistrar
+import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.options.ex.ConfigurableExtensionPointUtil
+import com.intellij.openapi.options.newEditor.SettingsDialogFactory
+import com.intellij.openapi.project.ProjectManager
+import io.netty.channel.ChannelHandlerContext
+import io.netty.handler.codec.http.FullHttpRequest
+import io.netty.handler.codec.http.QueryStringDecoder
+
+private const val SERVICE_NAME = "openSettings"
+
+internal class OpenSettingsService : RestService() {
+  override fun getServiceName() = SERVICE_NAME
+
+  override fun execute(urlDecoder: QueryStringDecoder, request: FullHttpRequest, context: ChannelHandlerContext): String? {
+    val name = urlDecoder.parameters().get("name")?.firstOrNull() ?: return "name parameter is not specified"
+
+    val effectiveProject = getLastFocusedOrOpenedProject() ?: ProjectManager.getInstance().defaultProject
+    val groups = listOf(ConfigurableExtensionPointUtil.getConfigurableGroup(effectiveProject, true))
+    val configurables = (SearchableOptionsRegistrar.getInstance() as SearchableOptionsRegistrarImpl).findByNameOnly(name, groups)
+    if (configurables.nameFullHits.isEmpty()) {
+      return "no configurables found"
+    }
+    val nameTopHit = configurables.nameFullHits.firstOrNull()
+    ApplicationManager.getApplication().invokeLater(Runnable {
+      SettingsDialogFactory.getInstance().create(effectiveProject, groups, nameTopHit, null).show()
+    }, effectiveProject.disposed)
+    sendOk(request, context)
+    return null
+  }
+}
\ No newline at end of file
diff --git a/platform/built-in-server/src/org/jetbrains/ide/RestService.java b/platform/built-in-server/src/org/jetbrains/ide/RestService.java
deleted file mode 100644 (file)
index f2fe561..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-// 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 org.jetbrains.ide;
-
-import com.google.common.base.Supplier;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-import com.google.gson.stream.MalformedJsonException;
-import com.intellij.ide.IdeBundle;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.util.NotNullLazyValue;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
-import com.intellij.openapi.util.registry.Registry;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.util.text.StringUtilRt;
-import com.intellij.openapi.wm.IdeFocusManager;
-import com.intellij.openapi.wm.IdeFrame;
-import com.intellij.ui.AppIcon;
-import com.intellij.util.ExceptionUtil;
-import com.intellij.util.ObjectUtils;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.io.NettyKt;
-import com.intellij.util.net.NetUtils;
-import io.netty.buffer.ByteBufInputStream;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.http.*;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.builtInWebServer.BuiltInWebServerKt;
-import org.jetbrains.io.Responses;
-
-import javax.swing.*;
-import java.awt.*;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static com.intellij.ide.impl.ProjectUtil.showYesNoDialog;
-
-/**
- * Document your service using <a href="http://apidocjs.com">apiDoc</a>. To extract big example from source code, consider to use *.coffee file near your source file.
- * (or Python/Ruby, but coffee recommended because it's plugin is lightweight). See {@link AboutHttpService} for example.
- *
- * Don't create JsonReader/JsonWriter directly, use only provided {@link #createJsonReader}, {@link #createJsonWriter} methods (to ensure that you handle in/out according to REST API guidelines).
- *
- * @see <a href="http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api">Best Practices for Designing a Pragmatic RESTful API</a>.
- */
-public abstract class RestService extends HttpRequestHandler {
-  protected static final Logger LOG = Logger.getInstance(RestService.class);
-  public static final String PREFIX = "api";
-
-  protected final NotNullLazyValue<Gson> gson = new NotNullLazyValue<Gson>() {
-    @NotNull
-    @Override
-    protected Gson compute() {
-      return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
-    }
-  };
-
-  private final LoadingCache<InetAddress, AtomicInteger> abuseCounter =
-    CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(CacheLoader.from((Supplier<AtomicInteger>)AtomicInteger::new));
-
-  private final Cache<String, Boolean> trustedOrigins =
-    CacheBuilder.newBuilder().maximumSize(1024).expireAfterWrite(1, TimeUnit.DAYS).build();
-
-  @Override
-  public final boolean isSupported(@NotNull FullHttpRequest request) {
-    if (!isMethodSupported(request.method())) {
-      return false;
-    }
-
-    String uri = request.uri();
-
-    if (isPrefixlessAllowed() && checkPrefix(uri, getServiceName())) {
-      return true;
-    }
-
-    String serviceName = getServiceName();
-    int minLength = 1 + PREFIX.length() + 1 + serviceName.length();
-    if (uri.length() >= minLength &&
-        uri.charAt(0) == '/' &&
-        uri.regionMatches(true, 1, PREFIX, 0, PREFIX.length()) &&
-        uri.regionMatches(true, 2 + PREFIX.length(), serviceName, 0, serviceName.length())) {
-      if (uri.length() == minLength) {
-        return true;
-      }
-      else {
-        char c = uri.charAt(minLength);
-        return c == '/' || c == '?';
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Service url must be "/api/$serviceName", but to preserve backward compatibility, prefixless path could be also supported
-   */
-  protected boolean isPrefixlessAllowed() {
-    return false;
-  }
-
-  /**
-   * Use human-readable name or UUID if it is an internal service.
-   */
-  @NotNull
-  protected abstract String getServiceName();
-
-  protected boolean isMethodSupported(@NotNull HttpMethod method) {
-    return method == HttpMethod.GET;
-  }
-
-  @Override
-  public final boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) {
-    try {
-      AtomicInteger counter = abuseCounter.get(((InetSocketAddress)context.channel().remoteAddress()).getAddress());
-      if (counter.incrementAndGet() > Registry.intValue("ide.rest.api.requests.per.minute", 30)) {
-        Responses.send(Responses.orInSafeMode(HttpResponseStatus.TOO_MANY_REQUESTS, HttpResponseStatus.OK), context.channel(), request);
-        return true;
-      }
-
-      if (!isHostTrusted(request, urlDecoder)) {
-        Responses.send(Responses.orInSafeMode(HttpResponseStatus.FORBIDDEN, HttpResponseStatus.OK), context.channel(), request);
-        return true;
-      }
-
-      String error = execute(urlDecoder, request, context);
-      if (error != null) {
-        Responses.send(HttpResponseStatus.BAD_REQUEST, context.channel(), request, error);
-      }
-    }
-    catch (Throwable e) {
-      HttpResponseStatus status;
-      // JsonReader exception
-      //noinspection InstanceofCatchParameter
-      if (e instanceof MalformedJsonException || (e instanceof IllegalStateException && e.getMessage().startsWith("Expected a "))) {
-        LOG.warn(e);
-        status = HttpResponseStatus.BAD_REQUEST;
-      }
-      else {
-        LOG.error(e);
-        status = HttpResponseStatus.INTERNAL_SERVER_ERROR;
-      }
-      Responses.send(status, context.channel(), request, ExceptionUtil.getThrowableText(e));
-    }
-    return true;
-  }
-
-  @SuppressWarnings("deprecation")
-  protected boolean isHostTrusted(@NotNull FullHttpRequest request, @NotNull QueryStringDecoder urlDecoder) throws InterruptedException, InvocationTargetException {
-    return isHostTrusted(request);
-  }
-
-  /**
-   * @deprecated Use {@link #isHostTrusted(FullHttpRequest, QueryStringDecoder)}
-   */
-  @SuppressWarnings("DeprecatedIsStillUsed")
-  @Deprecated
-  // e.g. upsource trust to configured host
-  protected boolean isHostTrusted(@NotNull FullHttpRequest request) throws InterruptedException, InvocationTargetException {
-    if (BuiltInWebServerKt.isSignedRequest(request)) {
-      return true;
-    }
-
-    String referrer = NettyKt.getOrigin(request);
-    if (referrer == null) {
-      referrer = NettyKt.getReferrer(request);
-    }
-
-    String host;
-    try {
-      host = StringUtil.nullize(referrer == null ? null : new URI(referrer).getHost());
-    }
-    catch (URISyntaxException ignored) {
-      return false;
-    }
-
-    Ref<Boolean> isTrusted = Ref.create();
-    if (host != null) {
-      if (NetUtils.isLocalhost(host)) {
-        isTrusted.set(true);
-      }
-      else {
-        isTrusted.set(trustedOrigins.getIfPresent(host));
-      }
-    }
-
-    if (isTrusted.isNull()) {
-      SwingUtilities.invokeAndWait(() -> {
-        AppIcon.getInstance().requestAttention(null, true);
-        isTrusted.set(showYesNoDialog(
-          IdeBundle.message("warning.use.rest.api", getServiceName(), ObjectUtils.chooseNotNull(host, "unknown host")),
-          "title.use.rest.api"));
-        if (host != null) {
-          trustedOrigins.put(host, isTrusted.get());
-        }
-      });
-    }
-    return isTrusted.get();
-  }
-
-  protected static void activateLastFocusedFrame() {
-    IdeFrame frame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame();
-    if (frame instanceof Window) {
-      ((Window)frame).toFront();
-    }
-  }
-
-  /**
-   * Return error or send response using {@link #sendOk(FullHttpRequest, ChannelHandlerContext)}, {@link #send(BufferExposingByteArrayOutputStream, HttpRequest, ChannelHandlerContext)}
-   */
-  @Nullable("error text or null if successful")
-  public abstract String execute(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException;
-
-  @NotNull
-  protected static JsonReader createJsonReader(@NotNull FullHttpRequest request) {
-    JsonReader reader = new JsonReader(new InputStreamReader(new ByteBufInputStream(request.content()), StandardCharsets.UTF_8));
-    reader.setLenient(true);
-    return reader;
-  }
-
-  @NotNull
-  protected static JsonWriter createJsonWriter(@NotNull OutputStream out) {
-    JsonWriter writer = new JsonWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
-    writer.setIndent("  ");
-    return writer;
-  }
-
-  @Nullable
-  protected static Project getLastFocusedOrOpenedProject() {
-    IdeFrame lastFocusedFrame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame();
-    Project project = lastFocusedFrame == null ? null : lastFocusedFrame.getProject();
-    if (project == null) {
-      Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
-      return openProjects.length > 0 ? openProjects[0] : null;
-    }
-    return project;
-  }
-
-  protected static void sendOk(@NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) {
-    sendStatus(HttpResponseStatus.OK, HttpUtil.isKeepAlive(request), context.channel());
-  }
-
-  protected static void sendStatus(@NotNull HttpResponseStatus status, boolean keepAlive, @NotNull Channel channel) {
-    DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status);
-    HttpUtil.setContentLength(response, 0);
-    Responses.addCommonHeaders(response);
-    Responses.addNoCache(response);
-    if (keepAlive) {
-      HttpUtil.setKeepAlive(response, true);
-    }
-    response.headers().set("X-Frame-Options", "Deny");
-    Responses.send(response, channel, !keepAlive);
-  }
-
-  protected static void send(@NotNull BufferExposingByteArrayOutputStream byteOut, @NotNull HttpRequest request, @NotNull ChannelHandlerContext context) {
-    HttpResponse response = Responses.response("application/json", Unpooled.wrappedBuffer(byteOut.getInternalBuffer(), 0, byteOut.size()));
-    sendResponse(request, context, response);
-  }
-
-  protected static void sendResponse(@NotNull HttpRequest request, @NotNull ChannelHandlerContext context, @NotNull HttpResponse response) {
-    Responses.addNoCache(response);
-    response.headers().set("X-Frame-Options", "Deny");
-    Responses.send(response, context.channel(), request);
-  }
-
-  @Nullable
-  protected static String getStringParameter(@NotNull String name, @NotNull QueryStringDecoder urlDecoder) {
-    return ContainerUtil.getLastItem(urlDecoder.parameters().get(name));
-  }
-
-  protected static int getIntParameter(@NotNull String name, @NotNull QueryStringDecoder urlDecoder) {
-    return StringUtilRt.parseInt(StringUtil.nullize(ContainerUtil.getLastItem(urlDecoder.parameters().get(name)), true), -1);
-  }
-
-  protected static boolean getBooleanParameter(@NotNull String name, @NotNull QueryStringDecoder urlDecoder) {
-    return getBooleanParameter(name, urlDecoder, false);
-  }
-
-  protected static boolean getBooleanParameter(@NotNull String name, @NotNull QueryStringDecoder urlDecoder, boolean defaultValue) {
-    List<String> values = urlDecoder.parameters().get(name);
-    if (ContainerUtil.isEmpty(values)) {
-      return defaultValue;
-    }
-
-    String value = values.get(values.size() - 1);
-    // if just name specified, so, true
-    return value.isEmpty() || Boolean.parseBoolean(value);
-  }
-}
diff --git a/platform/built-in-server/src/org/jetbrains/ide/RestService.kt b/platform/built-in-server/src/org/jetbrains/ide/RestService.kt
new file mode 100644 (file)
index 0000000..94e1ea7
--- /dev/null
@@ -0,0 +1,281 @@
+// 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 org.jetbrains.ide
+
+import com.google.common.base.Supplier
+import com.google.common.cache.CacheBuilder
+import com.google.common.cache.CacheLoader
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
+import com.google.gson.stream.JsonReader
+import com.google.gson.stream.JsonWriter
+import com.google.gson.stream.MalformedJsonException
+import com.intellij.ide.IdeBundle
+import com.intellij.ide.impl.ProjectUtil.showYesNoDialog
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.application.ModalityState
+import com.intellij.openapi.diagnostic.logger
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.project.ProjectManager
+import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream
+import com.intellij.openapi.util.registry.Registry
+import com.intellij.openapi.util.text.StringUtilRt
+import com.intellij.openapi.wm.IdeFocusManager
+import com.intellij.ui.AppIcon
+import com.intellij.util.ExceptionUtil
+import com.intellij.util.io.origin
+import com.intellij.util.io.referrer
+import com.intellij.util.net.NetUtils
+import com.intellij.util.text.nullize
+import io.netty.buffer.ByteBufInputStream
+import io.netty.buffer.Unpooled
+import io.netty.channel.Channel
+import io.netty.channel.ChannelHandlerContext
+import io.netty.handler.codec.http.*
+import org.jetbrains.builtInWebServer.isSignedRequest
+import org.jetbrains.io.*
+import java.awt.Window
+import java.io.IOException
+import java.io.OutputStream
+import java.lang.reflect.InvocationTargetException
+import java.net.InetAddress
+import java.net.InetSocketAddress
+import java.net.URI
+import java.net.URISyntaxException
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicInteger
+
+/**
+ * Document your service using [apiDoc](http://apidocjs.com). To extract big example from source code, consider to use *.coffee file near your source file.
+ * (or Python/Ruby, but coffee recommended because it's plugin is lightweight). See [AboutHttpService] for example.
+ *
+ * Don't create JsonReader/JsonWriter directly, use only provided [.createJsonReader], [.createJsonWriter] methods (to ensure that you handle in/out according to REST API guidelines).
+ *
+ * @see [Best Practices for Designing a Pragmatic REST API](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api).
+ */
+abstract class RestService : HttpRequestHandler() {
+  companion object {
+    @JvmField
+    val LOG = logger<RestService>()
+
+    const val PREFIX = "api"
+
+    @JvmStatic
+    protected fun activateLastFocusedFrame() {
+      (IdeFocusManager.getGlobalInstance().lastFocusedFrame as? Window)?.toFront()
+    }
+
+    @JvmStatic
+    protected fun createJsonReader(request: FullHttpRequest): JsonReader {
+      val reader = JsonReader(ByteBufInputStream(request.content()).reader())
+      reader.isLenient = true
+      return reader
+    }
+
+    @JvmStatic
+    protected fun createJsonWriter(out: OutputStream): JsonWriter {
+      val writer = JsonWriter(out.writer())
+      writer.setIndent("  ")
+      return writer
+    }
+
+    @JvmStatic
+    fun getLastFocusedOrOpenedProject(): Project? {
+      return IdeFocusManager.getGlobalInstance().lastFocusedFrame?.project ?: ProjectManager.getInstance().openProjects.firstOrNull()
+    }
+
+    @JvmStatic
+    protected fun sendOk(request: FullHttpRequest, context: ChannelHandlerContext) {
+      sendStatus(HttpResponseStatus.OK, HttpUtil.isKeepAlive(request), context.channel())
+    }
+
+    @JvmStatic
+    protected fun sendStatus(status: HttpResponseStatus, keepAlive: Boolean, channel: Channel) {
+      val response = DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status)
+      HttpUtil.setContentLength(response, 0)
+      response.addCommonHeaders()
+      response.addNoCache()
+      if (keepAlive) {
+        HttpUtil.setKeepAlive(response, true)
+      }
+      response.headers().set("X-Frame-Options", "Deny")
+      response.send(channel, !keepAlive)
+    }
+
+    @JvmStatic
+    protected fun send(byteOut: BufferExposingByteArrayOutputStream, request: HttpRequest, context: ChannelHandlerContext) {
+      val response = response("application/json", Unpooled.wrappedBuffer(byteOut.internalBuffer, 0, byteOut.size()))
+      sendResponse(request, context, response)
+    }
+
+    @JvmStatic
+    protected fun sendResponse(request: HttpRequest, context: ChannelHandlerContext, response: HttpResponse) {
+      response.addNoCache()
+      response.headers().set("X-Frame-Options", "Deny")
+      response.send(context.channel(), request)
+    }
+
+    @Suppress("SameParameterValue")
+    @JvmStatic
+    protected fun getStringParameter(name: String, urlDecoder: QueryStringDecoder): String? {
+      return urlDecoder.parameters().get(name)?.lastOrNull()
+    }
+
+    @JvmStatic
+    protected fun getIntParameter(name: String, urlDecoder: QueryStringDecoder): Int {
+      return StringUtilRt.parseInt(getStringParameter(name, urlDecoder).nullize(nullizeSpaces = true), -1)
+    }
+
+    @JvmOverloads
+    @JvmStatic
+    protected fun getBooleanParameter(name: String, urlDecoder: QueryStringDecoder, defaultValue: Boolean = false): Boolean {
+      val values = urlDecoder.parameters().get(name) ?: return defaultValue
+      // if just name specified, so, true
+      val value = values.lastOrNull() ?: return true
+      return value.toBoolean()
+    }
+  }
+
+  protected val gson: Gson by lazy {
+    GsonBuilder()
+      .setPrettyPrinting()
+      .disableHtmlEscaping()
+      .create()
+  }
+
+  private val abuseCounter = CacheBuilder.newBuilder()
+    .expireAfterWrite(1, TimeUnit.MINUTES)
+    .build<InetAddress, AtomicInteger>(CacheLoader.from(Supplier { AtomicInteger() }))
+
+  private val trustedOrigins = CacheBuilder.newBuilder()
+    .maximumSize(1024)
+    .expireAfterWrite(1, TimeUnit.DAYS)
+    .build<String, Boolean>()
+
+  /**
+   * Service url must be "/api/$serviceName", but to preserve backward compatibility, prefixless path could be also supported
+   */
+  protected open val isPrefixlessAllowed: Boolean
+    get() = false
+
+  /**
+   * Use human-readable name or UUID if it is an internal service.
+   */
+  protected abstract fun getServiceName(): String
+
+  override fun isSupported(request: FullHttpRequest): Boolean {
+    if (!isMethodSupported(request.method())) {
+      return false
+    }
+
+    val uri = request.uri()
+
+    if (isPrefixlessAllowed && checkPrefix(uri, getServiceName())) {
+      return true
+    }
+
+    val serviceName = getServiceName()
+    val minLength = 1 + PREFIX.length + 1 + serviceName.length
+    if (uri.length >= minLength &&
+        uri[0] == '/' &&
+        uri.regionMatches(1, PREFIX, 0, PREFIX.length, ignoreCase = true) &&
+        uri.regionMatches(2 + PREFIX.length, serviceName, 0, serviceName.length, ignoreCase = true)) {
+      if (uri.length == minLength) {
+        return true
+      }
+      else {
+        val c = uri[minLength]
+        return c == '/' || c == '?'
+      }
+    }
+    return false
+  }
+
+  protected open fun isMethodSupported(method: HttpMethod): Boolean {
+    return method === HttpMethod.GET
+  }
+
+  override fun process(urlDecoder: QueryStringDecoder, request: FullHttpRequest, context: ChannelHandlerContext): Boolean {
+    try {
+      val counter = abuseCounter.get((context.channel().remoteAddress() as InetSocketAddress).address)
+      if (counter.incrementAndGet() > Registry.intValue("ide.rest.api.requests.per.minute", 30)) {
+        HttpResponseStatus.TOO_MANY_REQUESTS.orInSafeMode(HttpResponseStatus.OK).send(context.channel(), request)
+        return true
+      }
+
+      if (!isHostTrusted(request, urlDecoder)) {
+        HttpResponseStatus.FORBIDDEN.orInSafeMode(HttpResponseStatus.OK).send(context.channel(), request)
+        return true
+      }
+
+      val error = execute(urlDecoder, request, context)
+      if (error != null) {
+        HttpResponseStatus.BAD_REQUEST.send(context.channel(), request, error)
+      }
+    }
+    catch (e: Throwable) {
+      val status: HttpResponseStatus?
+      // JsonReader exception
+      if (e is MalformedJsonException || e is IllegalStateException && e.message!!.startsWith("Expected a ")) {
+        LOG.warn(e)
+        status = HttpResponseStatus.BAD_REQUEST
+      }
+      else {
+        LOG.error(e)
+        status = HttpResponseStatus.INTERNAL_SERVER_ERROR
+      }
+      status.send(context.channel(), request, ExceptionUtil.getThrowableText(e))
+    }
+
+    return true
+  }
+
+  @Throws(InterruptedException::class, InvocationTargetException::class)
+  protected open fun isHostTrusted(request: FullHttpRequest, urlDecoder: QueryStringDecoder): Boolean {
+    @Suppress("DEPRECATION")
+    return isHostTrusted(request)
+  }
+
+  @Deprecated("Use {@link #isHostTrusted(FullHttpRequest, QueryStringDecoder)}")
+  @Throws(InterruptedException::class, InvocationTargetException::class)
+  // e.g. upsource trust to configured host
+  protected open fun isHostTrusted(request: FullHttpRequest): Boolean {
+    if (request.isSignedRequest()) {
+      return true
+    }
+
+    val referrer = request.origin ?: request.referrer
+    val host = try {
+      if (referrer == null) null else URI(referrer).host.nullize()
+    }
+    catch (ignored: URISyntaxException) {
+      return false
+    }
+
+    if (host != null) {
+      if (NetUtils.isLocalhost(host)) {
+        return true
+      }
+      else {
+        trustedOrigins.getIfPresent(host)?.let {
+          return it
+        }
+      }
+    }
+
+    var isTrusted = false
+    ApplicationManager.getApplication().invokeAndWait({
+                                                        AppIcon.getInstance().requestAttention(null, true)
+                                                        isTrusted = showYesNoDialog(IdeBundle.message("warning.use.rest.api", getServiceName(), host ?: "unknown host"), "title.use.rest.api")
+                                                        if (host != null) {
+                                                          trustedOrigins.put(host, isTrusted)
+                                                        }
+                                                      }, ModalityState.any())
+    return isTrusted
+  }
+
+  /**
+   * Return error or send response using [sendOk], [send]
+   */
+  @Throws(IOException::class)
+  abstract fun execute(urlDecoder: QueryStringDecoder, request: FullHttpRequest, context: ChannelHandlerContext): String?
+}
index 7c7c256d94b7bcf4e74618b0be519f5868cce2c1..44d4588d041a29d538d4b5af2a0a4122d3785139 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2000-2017 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.ide.util;
 
 import com.intellij.openapi.components.ServiceManager;
@@ -65,7 +65,7 @@ public abstract class PropertiesComponent extends SimpleModificationTracker {
 
   public abstract void setValues(@NonNls @NotNull String name, String[] values);
 
-  public static PropertiesComponent getInstance(Project project) {
+  public static PropertiesComponent getInstance(@NotNull Project project) {
     return ServiceManager.getService(project, PropertiesComponent.class);
   }
 
index 1c0f22c118d4410bf9330269663f70712278faf3..dc3cc637a0ab301a4b308f3917276e9be2f38192 100644 (file)
@@ -1,13 +1,8 @@
 // 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.
-
-/*
- * @author max
- */
 package com.intellij.openapi.util;
 
 import com.intellij.util.KeyedLazyInstance;
 import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -15,20 +10,23 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
+/**
+ * @author max
+ */
 public class ClassExtension<T> extends KeyedExtensionCollector<T, Class> {
-  public ClassExtension(@NonNls final String epName) {
+  public ClassExtension(@NotNull String epName) {
     super(epName);
   }
 
   @NotNull
   @Override
-  protected String keyToString(@NotNull final Class key) {
+  protected String keyToString(@NotNull Class key) {
     return key.getName();
   }
 
   @NotNull
   @Override
-  protected List<T> buildExtensions(@NotNull final String key, @NotNull final Class classKey) {
+  protected List<T> buildExtensions(@NotNull String key, @NotNull Class classKey) {
     final Set<String> allSupers = new LinkedHashSet<>();
     collectSupers(classKey, allSupers);
     return buildExtensionsWithInheritance(allSupers);
@@ -36,7 +34,7 @@ public class ClassExtension<T> extends KeyedExtensionCollector<T, Class> {
 
   private List<T> buildExtensionsWithInheritance(Set<String> supers) {
     List<KeyedLazyInstance<T>> extensions = getExtensions();
-    synchronized (lock) {
+    synchronized (myLock) {
       List<T> result = null;
       for (String aSuper : supers) {
         result = buildExtensionsFromExplicitRegistration(result, key -> aSuper.equals(key));
@@ -66,4 +64,4 @@ public class ClassExtension<T> extends KeyedExtensionCollector<T, Class> {
     final List<T> ts = forKey(t);
     return ts.isEmpty() ? null : ts.get(0);
   }
-}
+}
\ No newline at end of file
index 3ddea1e52cc74a0272806db1dc8628577c7e4ae7..e3ea2cb8c692b66dbb6457a044e1549750f712b4 100644 (file)
@@ -12,7 +12,6 @@ import com.intellij.util.SmartList;
 import com.intellij.util.containers.ContainerUtil;
 import gnu.trove.THashMap;
 import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -23,55 +22,54 @@ import java.util.function.Predicate;
 public class KeyedExtensionCollector<T, KeyT> implements ModificationTracker {
   private static final Logger LOG = Logger.getInstance(KeyedExtensionCollector.class);
 
-  // guarded by lock
+  protected final String myLock;
+
+  /** Guarded by {@link #myLock} */
   @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
   private Map<String, List<T>> myExplicitExtensions = Collections.emptyMap();
-  private final ConcurrentMap<String, List<T>> myCache = ContainerUtil.newConcurrentMap();
-
-  @NonNls protected final String lock;
 
+  private final ConcurrentMap<String, List<T>> myCache = ContainerUtil.newConcurrentMap();
   private final String myEpName;
   private final SimpleModificationTracker myTracker = new SimpleModificationTracker();
 
   private final ExtensionPointAndAreaListener<KeyedLazyInstance<T>> myListener = new ExtensionPointAndAreaListener<KeyedLazyInstance<T>>() {
     @Override
-    public void extensionAdded(@NotNull final KeyedLazyInstance<T> bean, @Nullable final PluginDescriptor pluginDescriptor) {
-      synchronized (lock) {
-      if (bean.getKey() == null) {
-        if (pluginDescriptor != null) {
-          throw new PluginException("No key specified for extension of class " + bean.getInstance().getClass(),
-                                    pluginDescriptor.getPluginId());
+    public void extensionAdded(@NotNull KeyedLazyInstance<T> bean, @Nullable PluginDescriptor pluginDescriptor) {
+      synchronized (myLock) {
+        if (bean.getKey() == null) {
+          if (pluginDescriptor != null) {
+            throw new PluginException("No key specified for extension of class " + bean.getInstance().getClass(), pluginDescriptor.getPluginId());
+          }
+          LOG.error("No key specified for extension of class " + bean.getInstance().getClass());
+          return;
         }
-        LOG.error("No key specified for extension of class " + bean.getInstance().getClass());
-        return;
-      }
-      myCache.remove(bean.getKey());
-      myTracker.incModificationCount();
+        myCache.remove(bean.getKey());
+        myTracker.incModificationCount();
       }
     }
 
     @Override
-    public void extensionRemoved(@NotNull final KeyedLazyInstance<T> bean, @Nullable final PluginDescriptor pluginDescriptor) {
-      synchronized (lock) {
-      myCache.remove(bean.getKey());
-      myTracker.incModificationCount();
+    public void extensionRemoved(@NotNull KeyedLazyInstance<T> bean, @Nullable PluginDescriptor pluginDescriptor) {
+      synchronized (myLock) {
+        myCache.remove(bean.getKey());
+        myTracker.incModificationCount();
       }
     }
 
     @Override
-    public void areaReplaced(@NotNull final ExtensionsArea area) {
+    public void areaReplaced(@NotNull ExtensionsArea area) {
       myCache.clear();
       myTracker.incModificationCount();
     }
   };
 
-  public KeyedExtensionCollector(@NonNls @NotNull String epName) {
+  public KeyedExtensionCollector(@NotNull String epName) {
     this(epName, null);
   }
 
-  public KeyedExtensionCollector(@NonNls @NotNull String epName, @Nullable Disposable parentDisposable) {
+  public KeyedExtensionCollector(@NotNull String epName, @Nullable Disposable parentDisposable) {
     myEpName = epName;
-    lock = "lock for KeyedExtensionCollector " + epName;
+    myLock = "lock for KeyedExtensionCollector " + epName;
 
     Extensions.getRootArea().addAvailabilityListener(epName, new ExtensionPointAvailabilityListener() {
       @Override
@@ -86,13 +84,13 @@ public class KeyedExtensionCollector<T, KeyT> implements ModificationTracker {
 
       @Override
       public void extensionPointRemoved(@NotNull ExtensionPoint extensionPoint) {
-        // no need to remove myListener - it should deregister automatically
+        // no need to remove myListener - it should unregister automatically
       }
     }, parentDisposable);
   }
 
   public void addExplicitExtension(@NotNull KeyT key, @NotNull T t) {
-    synchronized (lock) {
+    synchronized (myLock) {
       final String stringKey = keyToString(key);
       if (myExplicitExtensions == Collections.<String, List<T>>emptyMap()) {
         myExplicitExtensions = new THashMap<>();
@@ -110,7 +108,7 @@ public class KeyedExtensionCollector<T, KeyT> implements ModificationTracker {
   }
 
   public void removeExplicitExtension(@NotNull KeyT key, @NotNull T t) {
-    synchronized (lock) {
+    synchronized (myLock) {
       final String stringKey = keyToString(key);
       List<T> list = myExplicitExtensions.get(stringKey);
       if (list != null) {
@@ -157,9 +155,11 @@ public class KeyedExtensionCollector<T, KeyT> implements ModificationTracker {
   protected List<T> buildExtensions(@NotNull String stringKey, @NotNull KeyT key) {
     // compute out of our lock (https://youtrack.jetbrains.com/issue/IDEA-208060)
     List<KeyedLazyInstance<T>> extensions = getExtensions();
-    synchronized (lock) {
+    synchronized (myLock) {
       List<T> list = myExplicitExtensions.get(stringKey);
-      return ContainerUtil.notNullize(buildExtensionsFromExtensionPoint(list == null ? null : new ArrayList<>(list) /* mutable list expected here */, bean -> stringKey.equals(bean.getKey()), extensions));
+      List<T> result = list != null ? new ArrayList<>(list) : null;
+      result = buildExtensionsFromExtensionPoint(result, bean -> stringKey.equals(bean.getKey()), extensions);
+      return ContainerUtil.notNullize(result);
     }
   }
 
@@ -171,7 +171,9 @@ public class KeyedExtensionCollector<T, KeyT> implements ModificationTracker {
   }
 
   @Nullable
-  protected final List<T> buildExtensionsFromExtensionPoint(@Nullable List<T> result, @NotNull Predicate<? super KeyedLazyInstance<T>> isMyBean, @NotNull List<KeyedLazyInstance<T>> extensions) {
+  protected final List<T> buildExtensionsFromExtensionPoint(@Nullable List<T> result,
+                                                            @NotNull Predicate<? super KeyedLazyInstance<T>> isMyBean,
+                                                            @NotNull List<KeyedLazyInstance<T>> extensions) {
     for (KeyedLazyInstance<T> bean : extensions) {
       if (!isMyBean.test(bean)) {
         continue;
@@ -203,7 +205,7 @@ public class KeyedExtensionCollector<T, KeyT> implements ModificationTracker {
   @NotNull
   protected List<T> buildExtensions(@NotNull Set<String> keys) {
     List<KeyedLazyInstance<T>> extensions = getExtensions();
-    synchronized (lock) {
+    synchronized (myLock) {
       List<T> result = buildExtensionsFromExplicitRegistration(null, key -> keys.contains(key));
       result = buildExtensionsFromExtensionPoint(result, bean -> keys.contains(bean.getKey()), extensions);
       return ContainerUtil.notNullize(result);
@@ -234,7 +236,7 @@ public class KeyedExtensionCollector<T, KeyT> implements ModificationTracker {
   }
 
   public boolean hasAnyExtensions() {
-    synchronized (lock) {
+    synchronized (myLock) {
       if (!myExplicitExtensions.isEmpty()) return true;
       final ExtensionPoint<KeyedLazyInstance<T>> point = getPoint();
       return point != null && point.hasAnyExtensions();
@@ -259,4 +261,4 @@ public class KeyedExtensionCollector<T, KeyT> implements ModificationTracker {
       }
     }
   }
-}
+}
\ No newline at end of file
index 019ee46d81812cf0f39489065cd679f1de2a6406..3683c64f10b71dc467b4cc18f2cf0ea60176cfd1 100644 (file)
@@ -33,6 +33,7 @@ import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -306,13 +307,23 @@ public class PerformanceWatcher implements Disposable {
     for (int i = 0; i < commonPart.size() && i < stackTraceElements.length; i++) {
       StackTraceElement el1 = commonPart.get(commonPart.size() - i - 1);
       StackTraceElement el2 = stackTraceElements[stackTraceElements.length - i - 1];
-      if (!el1.equals(el2)) {
+      if (!compareStackTraceElements(el1, el2)) {
         return commonPart.subList(commonPart.size() - i, commonPart.size());
       }
     }
     return commonPart;
   }
 
+  // same as java.lang.StackTraceElement.equals, but do not care about the line number
+  static boolean compareStackTraceElements(StackTraceElement el1, StackTraceElement el2) {
+    if (el1 == el2) {
+      return true;
+    }
+    return el1.getClassName().equals(el2.getClassName()) &&
+           Objects.equals(el1.getMethodName(), el2.getMethodName()) &&
+           Objects.equals(el1.getFileName(), el2.getFileName());
+  }
+
   private class SwingThreadRunnable implements Runnable {
     private final long myCreationMillis;
 
index d16543b1fb59809038297dc9133ed65a8ff2dbd4..8ca7993b44ea280bd835605c21b3008437c97ad2 100644 (file)
@@ -51,7 +51,7 @@ internal class PgpTest {
   @Test
   fun decrypt() {
     val encryptedFile = Paths.get(SystemProperties.getUserHome(), "test.gpg")
-    assumeTrue(encryptedFile.exists())
+    assumeTrue("$encryptedFile doesn't exist", encryptedFile.exists())
 
     assertThat(Pgp().decrypt(encryptedFile.readBytes()).toString(Charsets.UTF_8)).isEqualTo("foo bar")
   }
index 4a0c8e7d7eb3b44d970e3980f6ce3ccc5d0f82ba..01e6c9c598b6dd466cd210c013312c214dfd4359 100644 (file)
@@ -424,10 +424,9 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i
       DefaultActionGroup actionGroup = new DefaultActionGroup();
       if (executionConsole instanceof BuildView) {
         actionGroup.addAll(((BuildView)executionConsole).getSwitchActions());
-        actionGroup.add(new ShowExecutionErrorsOnlyAction((BuildView)executionConsole));
+        actionGroup.add(BuildTreeFilters.createFilteringActionsGroup((BuildView)executionConsole));
       }
-      DefaultExecutionResult executionResult =
-        new DefaultExecutionResult(executionConsole, processHandler, actionGroup.getChildren(null));
+      DefaultExecutionResult executionResult = new DefaultExecutionResult(executionConsole, processHandler, actionGroup.getChildren(null));
       executionResult.setRestartActions(restartActions);
       return executionResult;
     }
index 44acb1ff4036c62f4369a4f5f8d5b67a81f519e6..abc9aef055a488705840c194ccc16397c415a177 100644 (file)
@@ -554,7 +554,7 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
     final AtomicInteger counter = new AtomicInteger();
     Messages.setTestDialog(new TestDialog() {
       @Override
-      public int show(String message) {
+      public int show(@NotNull String message) {
         counter.set(counter.get() + 1);
         return 0;
       }
@@ -566,7 +566,7 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
     final AtomicInteger counter = new AtomicInteger();
     Messages.setTestDialog(new TestDialog() {
       @Override
-      public int show(String message) {
+      public int show(@NotNull String message) {
         counter.set(counter.get() + 1);
         return 1;
       }
index b0215bcee9a89e6aa7ebaee317cc326319071215..d379696cfa5716fbf0b33262ed478a38771e3c84 100644 (file)
@@ -42,7 +42,7 @@ public class ExternalSystemException extends RuntimeException {
     this(message, null, quickFixes);
   }
 
-  public ExternalSystemException(@Nullable String message, @Nullable Throwable cause, @NotNull String... quickFixes) {
+public ExternalSystemException(@Nullable String message, @Nullable Throwable cause, @NotNull String... quickFixes) {
     super(extractMessage(message, cause));
     myQuickFixes = mergeArrays(cause instanceof ExternalSystemException
                                ? ((ExternalSystemException)cause).getQuickFixes()
index 853bb75d36acc1012f425ecfd7f8a8fbadbfd060..2cf64cce2e1eab56f4a76d122a225f4bdbad9540 100644 (file)
@@ -32,13 +32,4 @@ public abstract class Expression {
   public String getAdvertisingText() {
     return null;
   }
-
-  /**
-   * @return true if {@link Expression#calculateResult(com.intellij.codeInsight.template.ExpressionContext)} or
-   *                 {@link Expression#calculateQuickResult(com.intellij.codeInsight.template.ExpressionContext)}
-   *         require committed PSI for their calculation or false otherwise
-   */
-  public boolean requiresCommittedPSI() {
-    return true;
-  }
 }
index c80a695ad13addcfb2f8288a4129d8b019928c60..6a09c465aaac25638184d5137de98c305faf3deb 100644 (file)
@@ -38,11 +38,6 @@ public class TextExpression extends Expression {
   }
 
   @Override
-  public boolean requiresCommittedPSI() {
-    return false;
-  }
-
-  @Override
   public LookupElement[] calculateLookupItems(ExpressionContext expressionContext) {
     return LookupElement.EMPTY_ARRAY;
   }
index 41c537b3a310594eacf3a88755c2d57612ef29a0..a5709364989e0a337ce7de0bf387c86edb0de4ca 100644 (file)
@@ -4,6 +4,7 @@ package com.intellij.ide.actions.searcheverywhere;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.extensions.ExtensionPointName;
 import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.PossiblyDumbAware;
 import com.intellij.util.Processor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -16,7 +17,7 @@ import java.util.List;
 /**
  * @author Konstantin Bulenkov
  */
-public interface SearchEverywhereContributor<Item> {
+public interface SearchEverywhereContributor<Item> extends PossiblyDumbAware {
 
   ExtensionPointName<SearchEverywhereContributorFactory<?>> EP_NAME = ExtensionPointName.create("com.intellij.searchEverywhereContributor");
 
@@ -104,7 +105,8 @@ public interface SearchEverywhereContributor<Item> {
     return false;
   }
 
-  default boolean isDumbModeSupported() {
+  @Override
+  default boolean isDumbAware() {
     return true;
   }
 
index 31eae3d6d90839049fb71b4ef3bbafa6239093b0..56a40d18090b9b524dc2e9b8b488426d83d1eb00 100644 (file)
@@ -11,7 +11,6 @@ import com.intellij.execution.configurations.SimpleJavaParameters;
 import com.intellij.execution.process.OSProcessHandler;
 import com.intellij.ide.util.PropertiesComponent;
 import com.intellij.openapi.application.ApplicationNamesInfo;
-import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.OrderRootType;
 import com.intellij.openapi.util.Key;
@@ -353,7 +352,6 @@ public class JdkUtil {
       classpath.add(PathUtil.getJarPathForClass(commandLineWrapper));
       if (isUrlClassloader(vmParameters)) {
         classpath.add(PathUtil.getJarPathForClass(UrlClassLoader.class));
-        classpath.add(PathUtil.getJarPathForClass(PathManager.class));
         classpath.add(PathUtil.getJarPathForClass(StringUtilRt.class));
         classpath.add(PathUtil.getJarPathForClass(THashMap.class));
         //explicitly enumerate jdk classes as UrlClassLoader doesn't delegate to parent classloader when loading resources
index 4198b6c21de2feb330b4ac520aa2e89310984597..3d75ee632cd23af06a4386fb7a0e602c81769307 100644 (file)
@@ -30,6 +30,7 @@ public interface SdkModel {
    * Returns the list of SDKs in the table.
    * @return the SDK list.
    */
+  @NotNull
   Sdk[] getSdks();
 
   /**
@@ -46,7 +47,7 @@ public interface SdkModel {
    *
    * @param sdk the SDK to add
    */
-  void addSdk(Sdk sdk);
+  void addSdk(@NotNull Sdk sdk);
 
   /**
    * Allows to receive notifications when the JDK list has been changed by the
@@ -90,14 +91,15 @@ public interface SdkModel {
    *
    * @param listener the listener instance.
    */
-  void addListener(Listener listener);
+  void addListener(@NotNull Listener listener);
 
   /**
    * Removes a listener for receiving notifications about changes in the list.
    *
    * @param listener the listener instance.
    */
-  void removeListener(Listener listener);
+  void removeListener(@NotNull Listener listener);
 
+  @NotNull
   Listener getMulticaster();
 }
index 2a29e38899c9b7a655764d287ee139d505433d0f..5c30c2847f957d8976265494b6daf5e0be55e19c 100644 (file)
@@ -244,7 +244,7 @@ public abstract class SdkType implements SdkTypeId {
    * @param parentComponent    the parent component for showing the dialog.
    * @param selectedSdk        current selected sdk in parentComponent
    * @param sdkCreatedCallback the callback to which the created SDK is passed.
-   * @implSpec method's implementations should not add sdk to the jdkTable neither  invoke {@link SdkType#setupSdkPaths}. Only create and
+   * @implSpec method's implementations should not add sdk to the jdkTable neither invoke {@link SdkType#setupSdkPaths}. Only create and
    * and pass to the callback. The rest is done by {@link com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel#setupSdk(Sdk, Consumer)}
    */
   public void showCustomCreateUI(@NotNull SdkModel sdkModel,
index c6eab2b33fa131e3919e1c501ba67d0fd7bfb1b6..478266b4e72e0aa4c747535118abf4c2fed6d153 100644 (file)
@@ -64,7 +64,7 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig
 
   private final List<TextRange>       myPreviewRangesToHighlight = new ArrayList<>();
 
-  private final Editor myEditor;
+  private final EditorEx myEditor;
   private final CodeStyleSettings mySettings;
   private boolean myShouldUpdatePreview;
   protected static final int[] ourWrappings =
@@ -134,7 +134,7 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig
   }
 
   @Nullable
-  private Editor createEditor() {
+  private EditorEx createEditor() {
     if (StringUtil.isEmpty(getPreviewText())) return null;
     EditorFactory editorFactory = EditorFactory.getInstance();
     Document editorDocument = editorFactory.createDocument("");
@@ -159,7 +159,7 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig
   protected void updatePreview(boolean useDefaultSample) {
     if (myEditor == null) return;
     updateEditor(useDefaultSample);
-    updatePreviewHighlighter((EditorEx)myEditor);
+    updatePreviewHighlighter(myEditor);
   }
 
   private void updateEditor(boolean useDefaultSample) {
@@ -167,7 +167,6 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig
       return;
     }
 
-    Project project = ProjectUtil.guessCurrentProject(getPanel());
     if (myEditor.isDisposed()) return;
 
     if (myLastDocumentModificationStamp != myEditor.getDocument().getModificationStamp()) {
@@ -177,8 +176,19 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig
       myTextToReformat = StringUtil.convertLineSeparators(ObjectUtils.notNull(getPreviewText(), ""));
     }
 
+    updateEditorState(true);
+  }
+
+  protected void setEditorText(@NotNull String text, boolean updateHighlighter) {
+    myTextToReformat = StringUtil.convertLineSeparators(text);
+    if (updateHighlighter) updatePreviewHighlighter(myEditor);
+    updateEditorState(false);
+  }
+
+  private void updateEditorState(boolean collectChanges) {
     int currOffs = myEditor.getScrollingModel().getVerticalScrollOffset();
-    CommandProcessor.getInstance().executeCommand(project, () -> replaceText(project), null, null);
+    Project project = ProjectUtil.guessCurrentProject(getPanel());
+    CommandProcessor.getInstance().executeCommand(project, () -> replaceText(project, collectChanges), null, null);
 
     myEditor.getSettings().setRightMargin(getAdjustedRightMargin());
     myLastDocumentModificationStamp = myEditor.getDocument().getModificationStamp();
@@ -192,11 +202,11 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig
 
   protected abstract int getRightMargin();
 
-  private void replaceText(final Project project) {
+  private void replaceText(final Project project, boolean collectChanges) {
     ApplicationManager.getApplication().runWriteAction(() -> {
       try {
         Document beforeReformat = null;
-        if (myEditor.getDocument().getTextLength() > 0) {
+        if (collectChanges && myEditor.getDocument().getTextLength() > 0) {
           beforeReformat = collectChangesBeforeCurrentSettingsAppliance(project);
         }
 
@@ -596,6 +606,12 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig
     return myCurrentSettings;
   }
 
+@Nullable
+  protected CodeStyleSettings getModelSettings() {
+    CodeStyleSchemesModel model = myModel;
+    return model != null ? model.getCloneSettings(model.getSelectedScheme()) : null;
+  }
+
   public void setupCopyFromMenu(JPopupMenu copyMenu) {
     copyMenu.removeAll();
   }
index 050a00ae98e173759e1eefa278ef90b54a493867..c535feda28fa5319bdc7cb3f97a3482acff8466e 100644 (file)
@@ -584,7 +584,7 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane
     }
 
     @Nullable
-    private CommonCodeStyleSettings.IndentOptions getIndentOptions(CodeStyleSettings settings) {
+    protected CommonCodeStyleSettings.IndentOptions getIndentOptions(CodeStyleSettings settings) {
       return settings.getCommonSettings(getDefaultLanguage()).getIndentOptions();
     }
 
index 02ce1aa6509908cb460e29697b99333de274af9d..b07b2d41578b98046f8c892a5568094848518398 100644 (file)
@@ -164,6 +164,7 @@ public class ArrangementGroupingRulesControl extends JBTable {
         ArrangementGroupingComponent component = (ArrangementGroupingComponent)value;
         component.setRowIndex(row + 1);
         component.setHighlight(myRowUnderMouse == row || table.isRowSelected(row));
+        component.revalidate();
         return component;
       }
       else if (value instanceof ArrangementRepresentationAware) {
index db842f605c07009e9226f8b046ec0df9ace5106f..b76a6bd1f5d1ac8bc83ec9e3ff22d67ab251fd91 100644 (file)
                       <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
                     </constraints>
                     <properties>
+                      <labelFor value="3b679"/>
                       <text resource-bundle="messages/ApplicationBundle" key="combobox.richcopy.color.scheme"/>
                     </properties>
                   </component>
                   <component id="3b679" class="javax.swing.JComboBox" binding="myRichCopyColorSchemeComboBox">
                     <constraints>
-                      <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+                      <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
                     </constraints>
                     <properties/>
                   </component>
                       </component>
                       <component id="87620" class="javax.swing.JComboBox" binding="myStripTrailingSpacesCombo">
                         <constraints>
-                          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+                          <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
                         </constraints>
                         <properties/>
                       </component>
index 029d8a0d35d08caef48a92891c29f24100e780e2..3e10468e35cab53e05df769515b1bd21a59ae77d 100644 (file)
@@ -121,7 +121,7 @@ public abstract class AbstractViewManager implements ViewManager, BuildProgressL
     toolbarActions.removeAll();
     toolbarActions.addAll(view.createConsoleActions());
     toolbarActions.add(new PinBuildViewAction(buildsView));
-    toolbarActions.add(new ShowExecutionErrorsOnlyAction(view));
+    toolbarActions.add(BuildTreeFilters.createFilteringActionsGroup(view));
   }
 
   @Nullable
index 533174c4c1e70aa324bf9c945fa82cc9b86809cf..bc7c408872a8edda3c7111570fdcfaa69d201499 100644 (file)
@@ -11,16 +11,29 @@ import com.intellij.execution.process.ProcessHandler;
 import com.intellij.execution.ui.ConsoleView;
 import com.intellij.execution.ui.ConsoleViewContentType;
 import com.intellij.execution.ui.ExecutionConsole;
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.CommonActionsManager;
+import com.intellij.ide.IdeBundle;
+import com.intellij.ide.OccurenceNavigator;
+import com.intellij.ide.OccurenceNavigatorSupport;
 import com.intellij.ide.actions.EditSourceAction;
 import com.intellij.ide.ui.UISettings;
 import com.intellij.ide.util.treeView.NodeRenderer;
+import com.intellij.idea.ActionsBundle;
 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.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.actions.ToggleUseSoftWrapsToolbarAction;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.ex.util.EditorUtil;
+import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
+import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.io.FileUtil;
@@ -56,10 +69,8 @@ import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.TreeModel;
 import javax.swing.tree.TreePath;
 import java.awt.*;
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
@@ -77,7 +88,7 @@ import static com.intellij.util.ui.UIUtil.getTreeSelectionForeground;
 /**
  * @author Vladislav.Soroka
  */
-public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildConsoleView, Filterable<ExecutionNode> {
+public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildConsoleView, Filterable<ExecutionNode>, OccurenceNavigator {
   private static final Logger LOG = Logger.getInstance(BuildTreeConsoleView.class);
 
   @NonNls private static final String TREE = "tree";
@@ -94,13 +105,14 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
   private final Tree myTree;
   private final ExecutionNode myRootNode;
   private final ExecutionNode myBuildProgressRootNode;
-  @Nullable
-  private volatile Predicate<ExecutionNode> myExecutionTreeFilter;
+  private final Set<Predicate<ExecutionNode>> myNodeFilters;
+  private final ProblemOccurrenceNavigatorSupport myOccurrenceNavigatorSupport;
 
   public BuildTreeConsoleView(Project project,
                               BuildDescriptor buildDescriptor,
                               @Nullable ExecutionConsole executionConsole,
                               @NotNull BuildViewSettingsProvider buildViewSettingsProvider) {
+    myNodeFilters = ContainerUtil.newConcurrentSet();
     myProject = project;
     myWorkingDir = FileUtil.toSystemIndependentName(buildDescriptor.getWorkingDir());
 
@@ -125,6 +137,9 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
       new ConsoleViewHandler(myProject, myTree, myBuildProgressRootNode, this, executionConsole, buildViewSettingsProvider);
     myThreeComponentsSplitter.setSecondComponent(myConsoleViewHandler.getComponent());
     myPanel.add(myThreeComponentsSplitter, BorderLayout.CENTER);
+    BuildTreeFilters.install(this);
+    myRootNode.setFilter(getFilter());
+    myOccurrenceNavigatorSupport = new ProblemOccurrenceNavigatorSupport(myTree);
   }
 
   private void installContextMenu(@NotNull StartBuildEvent startBuildEvent) {
@@ -143,8 +158,14 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
       ActionUtil.copyFrom(edit, "EditSource");
       group.add(edit);
       group.addSeparator();
-      group.add(new ShowExecutionErrorsOnlyAction(this));
-
+      group.addAll(BuildTreeFilters.createFilteringActionsGroup(this));
+      group.addSeparator();
+      //Initializing prev and next occurrences actions
+      final CommonActionsManager actionsManager = CommonActionsManager.getInstance();
+      final AnAction prevAction = actionsManager.createPrevOccurenceAction(this);
+      group.add(prevAction);
+      final AnAction nextAction = actionsManager.createNextOccurenceAction(this);
+      group.add(nextAction);
       PopupHandler.installPopupHandler(myTree, group, "BuildView");
     });
   }
@@ -162,20 +183,35 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
     return true;
   }
 
+  @NotNull
   @Override
-  @Nullable
   public Predicate<ExecutionNode> getFilter() {
-    return myExecutionTreeFilter;
+    return executionNode -> executionNode == getBuildProgressRootNode() ||
+                            executionNode.isRunning() ||
+                            executionNode.isFailed() ||
+                            myNodeFilters.stream().anyMatch(predicate -> predicate.test(executionNode));
   }
 
   @Override
-  public void setFilter(@Nullable Predicate<ExecutionNode> executionTreeFilter) {
-    myExecutionTreeFilter = executionTreeFilter;
-    ExecutionNode buildProgressRootNode = getBuildProgressRootNode();
+  public void addFilter(@NotNull Predicate<ExecutionNode> executionTreeFilter) {
+    myNodeFilters.add(executionTreeFilter);
+    updateFilter();
+  }
+
+  @Override
+  public void removeFilter(@NotNull Predicate<ExecutionNode> filter) {
+    myNodeFilters.remove(filter);
+    updateFilter();
+  }
+
+  @Override
+  public boolean contains(@NotNull Predicate<ExecutionNode> filter) {
+    return myNodeFilters.contains(filter);
+  }
+
+  private void updateFilter() {
     ExecutionNode rootElement = getRootElement();
-    Predicate<ExecutionNode> predicate = executionTreeFilter == null ? null :
-                                         node -> node == buildProgressRootNode || executionTreeFilter.test(node);
-    rootElement.setFilter(predicate);
+    rootElement.setFilter(getFilter());
     scheduleUpdate(rootElement);
   }
 
@@ -315,6 +351,38 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
     }
   }
 
+  @Override
+  public boolean hasNextOccurence() {
+    return myOccurrenceNavigatorSupport.hasNextOccurence();
+  }
+
+  @Override
+  public boolean hasPreviousOccurence() {
+    return myOccurrenceNavigatorSupport.hasPreviousOccurence();
+  }
+
+  @Override
+  public OccurenceInfo goNextOccurence() {
+    return myOccurrenceNavigatorSupport.goNextOccurence();
+  }
+
+  @Override
+  public OccurenceInfo goPreviousOccurence() {
+    return myOccurrenceNavigatorSupport.goPreviousOccurence();
+  }
+
+  @NotNull
+  @Override
+  public String getNextOccurenceActionName() {
+    return myOccurrenceNavigatorSupport.getNextOccurenceActionName();
+  }
+
+  @NotNull
+  @Override
+  public String getPreviousOccurenceActionName() {
+    return myOccurrenceNavigatorSupport.getPreviousOccurenceActionName();
+  }
+
   @NotNull
   private static TreeVisitor visitor(@NotNull ExecutionNode executionNode) {
     return path -> {
@@ -502,7 +570,13 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
     if (eventKind == MessageEvent.Kind.ERROR || eventKind == MessageEvent.Kind.WARNING) {
       SimpleNode p = parentNode;
       do {
-        ((ExecutionNode)p).reportChildMessageKind(eventKind);
+        ExecutionNode executionNode = (ExecutionNode)p;
+        boolean warningUpdate = eventKind == MessageEvent.Kind.WARNING && !executionNode.hasWarnings();
+        executionNode.reportChildMessageKind(eventKind);
+        if (warningUpdate) {
+          executionNode.cleanUpCache();
+          scheduleUpdate(executionNode);
+        }
       }
       while ((p = p.getParent()) instanceof ExecutionNode);
       scheduleUpdate(getRootElement());
@@ -625,14 +699,21 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
         myPanel.setVisible(false);
       }
       JComponent consoleComponent = emptyConsole.getComponent();
-      AnAction[] consoleActions = emptyConsole.createConsoleActions();
       consoleComponent.setFocusable(true);
       final Color editorBackground = EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground();
       consoleComponent.setBorder(new CompoundBorder(IdeBorderFactory.createBorder(SideBorder.RIGHT),
                                                     new SideBorder(editorBackground, SideBorder.LEFT)));
       myPanel.add(myView.getComponent(), BorderLayout.CENTER);
-      final ActionToolbar toolbar = ActionManager.getInstance()
-        .createActionToolbar("BuildResults", new DefaultActionGroup(consoleActions), false);
+      DefaultActionGroup consoleActionsGroup = new DefaultActionGroup();
+      consoleActionsGroup.add(new ToggleUseSoftWrapsToolbarAction(SoftWrapAppliancePlaces.CONSOLE) {
+        @Nullable
+        @Override
+        protected Editor getEditor(@NotNull AnActionEvent e) {
+          return ConsoleViewHandler.this.getEditor();
+        }
+      });
+      consoleActionsGroup.add(new ScrollEditorToTheEndAction(this));
+      final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("BuildConsole", consoleActionsGroup, false);
       myPanel.add(toolbar.getComponent(), BorderLayout.EAST);
       tree.addTreeSelectionListener(e -> {
         TreePath path = e.getPath();
@@ -647,12 +728,28 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
       Disposer.register(parentDisposable, emptyConsole);
     }
 
+    @Nullable
+    private ExecutionConsole getCurrentConsole() {
+      String nodeConsoleViewName = myNodeConsoleViewName.get();
+      if (nodeConsoleViewName == null) return null;
+      return myView.getView(nodeConsoleViewName);
+    }
+
+    @Nullable
+    private Editor getEditor() {
+      ExecutionConsole console = getCurrentConsole();
+      if (console instanceof ConsoleViewImpl) {
+        return ((ConsoleViewImpl)console).getEditor();
+      }
+      return null;
+    }
+
     private boolean setNode(@NotNull ExecutionNode node) {
       String nodeConsoleViewName = getNodeConsoleViewName(node);
-      List<Consumer<BuildTextConsoleView>> deferredOutput = deferredNodeOutput.get(nodeConsoleViewName);
       myNodeConsoleViewName.set(nodeConsoleViewName);
       ExecutionConsole view = myView.getView(nodeConsoleViewName);
       if (view != null) {
+        List<Consumer<BuildTextConsoleView>> deferredOutput = deferredNodeOutput.get(nodeConsoleViewName);
         if (view instanceof BuildTextConsoleView && deferredOutput != null && !deferredOutput.isEmpty()) {
           deferredNodeOutput.remove(nodeConsoleViewName);
           deferredOutput.forEach(consumer -> consumer.accept((BuildTextConsoleView)view));
@@ -662,6 +759,7 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
         return true;
       }
 
+      List<Consumer<BuildTextConsoleView>> deferredOutput = deferredNodeOutput.get(nodeConsoleViewName);
       if (deferredOutput != null && !deferredOutput.isEmpty()) {
         BuildTextConsoleView textConsoleView = new BuildTextConsoleView(myProject, true);
         deferredNodeOutput.remove(nodeConsoleViewName);
@@ -745,6 +843,77 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
     }
   }
 
+  private static class ProblemOccurrenceNavigatorSupport extends OccurenceNavigatorSupport {
+    ProblemOccurrenceNavigatorSupport(final Tree tree) {
+      super(tree);
+    }
+
+    @Override
+    protected Navigatable createDescriptorForNode(@NotNull DefaultMutableTreeNode node) {
+      Object userObject = node.getUserObject();
+      if (!(userObject instanceof ExecutionNode)) {
+        return null;
+      }
+      final ExecutionNode executionNode = (ExecutionNode)userObject;
+      if (executionNode.getChildCount() > 0 || !executionNode.hasWarnings() && !executionNode.isFailed()) {
+        return null;
+      }
+      List<Navigatable> navigatables = executionNode.getNavigatables();
+      if (!navigatables.isEmpty()) {
+        return navigatables.get(0);
+      }
+      return null;
+    }
+
+    @NotNull
+    @Override
+    public String getNextOccurenceActionName() {
+      return IdeBundle.message("action.next.problem");
+    }
+
+    @NotNull
+    @Override
+    public String getPreviousOccurenceActionName() {
+      return IdeBundle.message("action.previous.problem");
+    }
+  }
+
+  private static class ScrollEditorToTheEndAction extends ToggleAction implements DumbAware {
+    @NotNull
+    private final ConsoleViewHandler myConsoleViewHandler;
+
+    ScrollEditorToTheEndAction(@NotNull ConsoleViewHandler handler) {
+      myConsoleViewHandler = handler;
+      final String message = ActionsBundle.message("action.EditorConsoleScrollToTheEnd.text");
+      getTemplatePresentation().setDescription(message);
+      getTemplatePresentation().setText(message);
+      getTemplatePresentation().setIcon(AllIcons.RunConfigurations.Scroll_down);
+    }
+
+    @Override
+    public boolean isSelected(@NotNull AnActionEvent e) {
+      Editor editor = myConsoleViewHandler.getEditor();
+      if (editor == null) return false;
+      Document document = editor.getDocument();
+      return document.getLineCount() == 0 || document.getLineNumber(editor.getCaretModel().getOffset()) == document.getLineCount() - 1;
+    }
+
+    @Override
+    public void setSelected(@NotNull AnActionEvent e, boolean state) {
+      Editor editor = myConsoleViewHandler.getEditor();
+      if (editor == null) return;
+      if (state) {
+        EditorUtil.scrollToTheEnd(editor);
+      }
+      else {
+        int lastLine = Math.max(0, editor.getDocument().getLineCount() - 1);
+        LogicalPosition currentPosition = editor.getCaretModel().getLogicalPosition();
+        LogicalPosition position = new LogicalPosition(Math.max(0, Math.min(currentPosition.line, lastLine - 1)), currentPosition.column);
+        editor.getCaretModel().moveToLogicalPosition(position);
+      }
+    }
+  }
+
   private static class MyTree extends Tree {
     private MyTree(TreeModel treemodel) {
       super(treemodel);
index 8f8d586ada65cca0796d4ac2ac6ae8432bb9fc08..2e09cfec376524ecb9ddaf389b922e6646673f36 100644 (file)
@@ -32,6 +32,7 @@ import com.intellij.execution.ui.ConsoleViewContentType;
 import com.intellij.execution.ui.ExecutionConsole;
 import com.intellij.execution.ui.RunContentDescriptor;
 import com.intellij.execution.ui.actions.CloseAction;
+import com.intellij.ide.OccurenceNavigator;
 import com.intellij.ide.actions.PinActiveTabAction;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.application.ApplicationManager;
@@ -56,7 +57,7 @@ import java.util.function.Supplier;
  */
 @ApiStatus.Experimental
 public class BuildView extends CompositeView<ExecutionConsole>
-  implements BuildProgressListener, ConsoleView, DataProvider, Filterable<ExecutionNode> {
+  implements BuildProgressListener, ConsoleView, DataProvider, Filterable<ExecutionNode>, OccurenceNavigator {
   public static final String CONSOLE_VIEW_NAME = "consoleView";
   private final AtomicReference<StartBuildEvent> myStartBuildEventRef = new AtomicReference<>();
   private final BuildDescriptor myBuildDescriptor;
@@ -365,17 +366,75 @@ public class BuildView extends CompositeView<ExecutionConsole>
     return getEventView() != null;
   }
 
+  @NotNull
   @Override
   public Predicate<ExecutionNode> getFilter() {
     BuildTreeConsoleView eventView = getEventView();
-    return eventView == null ? null : eventView.getFilter();
+    return eventView == null ? executionNode -> true : eventView.getFilter();
   }
 
   @Override
-  public void setFilter(Predicate<ExecutionNode> filter) {
+  public void addFilter(@NotNull Predicate<ExecutionNode> filter) {
     BuildTreeConsoleView eventView = getEventView();
     if (eventView != null) {
-      eventView.setFilter(filter);
+      eventView.addFilter(filter);
+    }
+  }
+
+  @Override
+  public void removeFilter(@NotNull Predicate<ExecutionNode> filter) {
+    BuildTreeConsoleView eventView = getEventView();
+    if (eventView != null) {
+      eventView.removeFilter(filter);
+    }
+  }
+
+  @Override
+  public boolean contains(@NotNull Predicate<ExecutionNode> filter) {
+    BuildTreeConsoleView eventView = getEventView();
+    return eventView != null && eventView.contains(filter);
+  }
+
+  @NotNull
+  private OccurenceNavigator getOccurenceNavigator() {
+    BuildTreeConsoleView eventView = getEventView();
+    if (eventView != null) return eventView;
+    ExecutionConsole executionConsole = getConsoleView();
+    if (executionConsole instanceof OccurenceNavigator) {
+      return (OccurenceNavigator)executionConsole;
     }
+    return EMPTY;
+  }
+
+  @Override
+  public boolean hasNextOccurence() {
+    return getOccurenceNavigator().hasNextOccurence();
+  }
+
+  @Override
+  public boolean hasPreviousOccurence() {
+    return getOccurenceNavigator().hasPreviousOccurence();
+  }
+
+  @Override
+  public OccurenceInfo goNextOccurence() {
+    return getOccurenceNavigator().goNextOccurence();
+  }
+
+  @Override